1. 查询InfiniBand设备列表

任务说明

编写一个C程序,调用InfiniBand Verbs API枚举系统中可用的IB设备,输出每个设备的名称、物理端口总数以及设备状态(是否可用)。程序仅负责设备发现与属性读取,不涉及连接管理或数据传输。

环境依赖

  • Linux系统,已安装InfiniBand驱动(如mlx4_core、mlx5_core)
  • libibverbs开发库(Debian/Ubuntu: libibverbs-dev;RHEL/CentOS: libibverbs-devel)
  • 编译时链接 -libverbs

关键完整代码

#include <stdio.h>
#include <stdlib.h>
#include <infiniband/verbs.h>

int main(void) {
    struct ibv_device **dev_list;
    int num_devices;
    int i;

    // 枚举系统中所有IB设备
    dev_list = ibv_get_device_list(&num_devices);
    if (!dev_list) {
        perror("ibv_get_device_list");
        return 1;
    }

    if (num_devices == 0) {
        printf("未检测到InfiniBand设备\n");
        ibv_free_device_list(dev_list);
        return 0;
    }

    printf("检测到 %d 个InfiniBand设备:\n", num_devices);

    for (i = 0; i < num_devices; i++) {
        struct ibv_context *ctx;
        struct ibv_device_attr attr;
        const char *name = ibv_get_device_name(dev_list[i]);
        const char *dev_state;

        // 打开设备上下文以查询属性
        ctx = ibv_open_device(dev_list[i]);
        if (!ctx) {
            perror("ibv_open_device");
            continue;
        }

        // 查询设备属性
        if (ibv_query_device(ctx, &attr) != 0) {
            perror("ibv_query_device");
            ibv_close_device(ctx);
            continue;
        }

        // 判断设备状态:根据sysfs中的state字段
        char state_path[256];
        FILE *fp;
        char state_buf[32];
        snprintf(state_path, sizeof(state_path),
                 "/sys/class/infiniband/%s/state", name);
        fp = fopen(state_path, "r");
        if (fp) {
            if (fgets(state_buf, sizeof(state_buf), fp))
                dev_state = state_buf;
            else
                dev_state = "未知";
            fclose(fp);
        } else {
            dev_state = "未知";
        }

        printf("  设备 %d:\n", i + 1);
        printf("    名称: %s\n", name);
        printf("    端口数: %u\n", attr.phys_port_cnt);
        printf("    状态: %s", dev_state);
        if (dev_state[strlen(dev_state) - 1] != '\n')
            printf("\n");

        ibv_close_device(ctx);
    }

    ibv_free_device_list(dev_list);
    return 0;
}

编译与运行

gcc -o ib_list ib_list.c -libverbs
sudo ./ib_list   # 读取sysfs需要root权限

验证方法

在装有InfiniBand适配器的机器上运行程序,预期输出包含设备名称(如 mlx5_0)、端口数(如 1)以及状态(如 ACTIVE)。可通过以下方式交叉验证:

  • 执行 ibstat 命令对比设备名称与端口数是否一致
  • 执行 cat /sys/class/infiniband/mlx5_0/state 对比状态字段

若系统无IB设备,程序输出“未检测到InfiniBand设备”并正常退出,此时可通过 ibv_devinfo 命令确认系统确实无设备。

常见问题

  • 编译报错找不到头文件:确认已安装libibverbs开发包。
  • 打开设备失败:检查当前用户是否有权限访问 /dev/infiniband/,必要时使用sudo运行。
  • 状态读取为“未知”:部分虚拟设备或驱动可能不暴露sysfs状态节点,此时以 ibstat 输出为准。