2. 获取设备属性
任务目标
编写一个命令行程序,通过输入设备名称(如 mlx5_0),查询并输出该 InfiniBand 设备的节点 GUID、设备版本、固件版本、硬件版本等属性。程序需处理设备不存在或打开失败的错误场景。
核心实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <infiniband/verbs.h>
static void print_device_attr(const char *dev_name) {
struct ibv_device **dev_list;
struct ibv_device *dev = NULL;
struct ibv_context *ctx = NULL;
struct ibv_device_attr attr;
int i;
dev_list = ibv_get_device_list(NULL);
if (!dev_list) {
fprintf(stderr, "无法获取设备列表\n");
exit(1);
}
for (i = 0; dev_list[i]; ++i) {
if (strcmp(ibv_get_device_name(dev_list[i]), dev_name) == 0) {
dev = dev_list[i];
break;
}
}
if (!dev) {
fprintf(stderr, "设备 %s 不存在\n", dev_name);
ibv_free_device_list(dev_list);
exit(1);
}
ctx = ibv_open_device(dev);
if (!ctx) {
fprintf(stderr, "打开设备 %s 失败\n", dev_name);
ibv_free_device_list(dev_list);
exit(1);
}
memset(&attr, 0, sizeof(attr));
if (ibv_query_device(ctx, &attr) != 0) {
fprintf(stderr, "查询设备属性失败\n");
ibv_close_device(ctx);
ibv_free_device_list(dev_list);
exit(1);
}
printf("设备名称: %s\n", dev_name);
printf("节点 GUID: 0x%016llx\n", (unsigned long long)attr.node_guid);
printf("设备版本: %d\n", attr.device_version);
printf("固件版本: %s\n", attr.fw_ver);
printf("硬件版本: %s\n", attr.hw_ver);
printf("最大 QP 数: %d\n", attr.max_qp);
printf("最大 CQ 数: %d\n", attr.max_cq);
ibv_close_device(ctx);
ibv_free_device_list(dev_list);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "用法: %s <设备名>\n", argv[0]);
fprintf(stderr, "示例: %s mlx5_0\n", argv[0]);
return 1;
}
print_device_attr(argv[1]);
return 0;
}
编译与运行
# 编译(需安装 libibverbs-dev)
gcc -o query_dev query_dev.c -libverbs
# 查询设备属性
./query_dev mlx5_0
验证方法
程序执行后,观察输出是否包含以下字段:
- 节点 GUID:非零的 64 位十六进制数
- 固件版本:形如
xx.xx.xxxx的字符串 - 硬件版本:非空字符串
- 设备版本:整数值
可通过 ibv_devinfo -v 命令交叉验证输出结果的一致性。若输入不存在的设备名(如 ./query_dev fake_dev),程序应输出错误信息并以非零状态退出。
预期输出示例
设备名称: mlx5_0
节点 GUID: 0x248a070300a1b2c3
设备版本: 0
固件版本: 16.32.1010
硬件版本: 0x0000000000000000
最大 QP 数: 131072
最大 CQ 数: 16777216
常见问题
- 编译报错找不到头文件:安装
libibverbs-dev包(Ubuntu/Debian)或rdma-core-devel(RHEL/CentOS)。 - 运行提示设备不存在:先执行
ibv_devinfo -l查看系统实际可用的设备名称。 - 权限不足:部分系统需要 root 权限或加入
rdma用户组才能访问 InfiniBand 设备。