2. 使用DOCA SDK编译第一个程序

任务目标

编写一个基于DOCA SDK的最小C程序,调用DOCA核心API读取当前DPU的设备信息(如PCIe地址、固件版本),并编译运行验证DOCA开发环境可用。本案例聚焦于从源码到可执行文件的完整编译链路,不涉及DPU业务功能开发。

环境与依赖

  • 硬件:NVIDIA BlueField-3 DPU(或兼容的BlueField-2/3平台)
  • 操作系统:Ubuntu 22.04(DPU内置或Host交叉编译环境)
  • DOCA SDK 2.x(已安装并配置环境变量)
  • 编译工具:gcc、make、pkg-config

确认环境就绪:

doca_version   # 应输出DOCA版本号
pkg-config --modversion libdoca   # 应输出库版本

完整实现代码

创建文件 print_dpu_info.c:

#include <stdio.h>
#include <string.h>
#include <doca_dev.h>
#include <doca_error.h>
#include <doca_log.h>

DOCA_LOG_REGISTER(PRINT_DPU_INFO);

int main(int argc, char *argv[]) {
    doca_error_t result;
    struct doca_dev *dev = NULL;
    const char *pci_addr;
    const char *flavor;
    uint32_t pcie_vendor_id, pcie_device_id;

    /* 初始化DOCA日志系统 */
    result = doca_log_init();
    if (result != DOCA_SUCCESS) {
        fprintf(stderr, "日志初始化失败: %s\n", doca_error_get_descr(result));
        return EXIT_FAILURE;
    }

    /* 打开第一个可用DPU设备 */
    result = doca_dev_open(NULL, &dev);
    if (result != DOCA_SUCCESS) {
        DOCA_LOG_ERR("无法打开DPU设备: %s", doca_error_get_descr(result));
        doca_log_destroy();
        return EXIT_FAILURE;
    }

    /* 获取设备信息 */
    result = doca_dev_get_pci_addr(dev, &pci_addr);
    if (result != DOCA_SUCCESS) {
        DOCA_LOG_ERR("获取PCIe地址失败: %s", doca_error_get_descr(result));
        goto cleanup;
    }

    result = doca_dev_get_flavor(dev, &flavor);
    if (result != DOCA_SUCCESS) {
        DOCA_LOG_ERR("获取设备型号失败: %s", doca_error_get_descr(result));
        goto cleanup;
    }

    result = doca_dev_get_pcie_vendor_id(dev, &pcie_vendor_id);
    if (result != DOCA_SUCCESS) {
        DOCA_LOG_ERR("获取厂商ID失败: %s", doca_error_get_descr(result));
        goto cleanup;
    }

    result = doca_dev_get_pcie_device_id(dev, &pcie_device_id);
    if (result != DOCA_SUCCESS) {
        DOCA_LOG_ERR("获取设备ID失败: %s", doca_error_get_descr(result));
        goto cleanup;
    }

    /* 打印信息 */
    DOCA_LOG_INFO("=== DPU 设备信息 ===");
    DOCA_LOG_INFO("PCIe地址: %s", pci_addr);
    DOCA_LOG_INFO("设备型号: %s", flavor);
    DOCA_LOG_INFO("PCIe Vendor ID: 0x%04x", pcie_vendor_id);
    DOCA_LOG_INFO("PCIe Device ID: 0x%04x", pcie_device_id);

cleanup:
    doca_dev_close(dev);
    doca_log_destroy();
    return (result == DOCA_SUCCESS) ? EXIT_SUCCESS : EXIT_FAILURE;
}

编译与运行

创建Makefile(或直接使用命令行编译):

# Makefile
CFLAGS = $(shell pkg-config --cflags libdoca)
LDLIBS = $(shell pkg-config --libs libdoca)

print_dpu_info: print_dpu_info.c
	gcc -o $@ $< $(CFLAGS) $(LDLIBS)

clean:
	rm -f print_dpu_info

编译并运行:

make
sudo ./print_dpu_info

需要sudo权限以访问DPU设备节点。

验证方法与通过标准

  • 编译通过:make无报错,生成可执行文件print_dpu_info。
  • 运行成功:程序退出码为0,日志输出包含以下字段:
=== DPU 设备信息 ===
PCIe地址: 03:00.0
设备型号: BlueField-3
PCIe Vendor ID: 0x15b3
PCIe Device ID: 0xa2d2

以上为预期输出示例,实际值取决于具体硬件。判定通过条件:程序能正常打开设备并打印出非空的PCIe地址和设备型号,且退出码为0。

常见问题

  • 设备打开失败:确认已安装DOCA驱动(doca_device_list命令能看到设备),且当前用户有/dev/doca*访问权限。
  • pkg-config找不到库:执行export PKG_CONFIG_PATH=/opt/mellanox/doca/lib/pkgconfig:$PKG_CONFIG_PATH。
  • 编译警告:若提示隐式函数声明,检查DOCA头文件路径是否正确包含doca_dev.h。