当前想适配一款设备,底层走的mctp over pcie的协议,设备方会提供封装好的库.so库文件和.h头文件,由如下2个疑问:
1.我这边要怎样把该.so库文件和.h头文件集成到组件里面并实现调用呢?
2. 设备方提供的so库文件底层使用的是mctp over pcie的协议,so库文件需要怎样针对当前BMC的代码做单独的适配么?
当前想适配一款设备,底层走的mctp over pcie的协议,设备方会提供封装好的库.so库文件和.h头文件,由如下2个疑问:
1.我这边要怎样把该.so库文件和.h头文件集成到组件里面并实现调用呢?
2. 设备方提供的so库文件底层使用的是mctp over pcie的协议,so库文件需要怎样针对当前BMC的代码做单独的适配么?
答案内容由AI生成,仅供参考:
总结:完整操作清单
| 步骤 | 操作项 |
|---|---|
| 1 | 创建 vendor/ 目录存放 .h 和 .so |
| 2 | 修改 CMakeLists.txt 引入头文件和链接库 |
| 3 | 确保 .so 被复制到最终镜像的 /usr/lib64 或组件目录 |
| 4 | 编写 C/Lua 封装代码调用 API |
| 5 | 检查依赖:是否需 libmctp.so, MCTP_LIB, 或特定 PCIe 支持 |
| 6 | 若用于 QEMU:在 manifest 中配置 PCIe 卡和固件路径 |
| 7 | (推荐)将第三方库打包为 Conan 组件,提升复用性和版本管理能力 |
在 OpenUBMC 系统中,集成第三方提供的 .so 动态库和 .h 头文件以实现特定设备(如通过 MCTP over PCIe 协议通信的设备)的适配是一个典型且常见的南向驱动开发任务。以下是基于现有知识、架构设计和实践流程的完整解决方案。
.so 库和 .h 头文件集成到组件中并实现调用?建议在你的组件目录下创建一个标准的第三方库结构,例如:
your_component/
├── vendor/
│ └── third_party_device/
│ ├── include/ # 存放 .h 头文件
│ │ └── device_api.h
│ └── lib/
│ └── libdevice_api.so
├── src/
│ └── your_code.c
├── CMakeLists.txt
└── conanfile.py (或依赖 manifest.yml)
CMakeLists.txt,引入头文件与库路径在组件构建脚本中添加头文件路径和链接库:
# 添加头文件搜索路径
target_include_directories(${TARGET_LIB}
PRIVATE ${PROJECT_SOURCE_DIR}/vendor/third_party_device/include
)
# 将 .so 文件复制到输出目录,并链接
add_custom_command(
TARGET ${TARGET_LIB} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${PROJECT_SOURCE_DIR}/vendor/third_party_device/lib/libdevice_api.so"
"${CMAKE_BINARY_DIR}/output/lib/"
)
# 链接动态库(注意:需确保 runtime 路径正确)
target_link_libraries(${TARGET_LIB}
PRIVATE /path/to/built/libdevice_api.so # 或使用 $ORIGIN 等机制
)
注意:如果
.so是第三方闭源库,不能重新编译,应避免硬编码绝对路径,使用$ORIGIN控制RPATH。
#include "device_api.h"
void init_device() {
int ret = device_open("/dev/mctp0"); // 假设接口由第三方提供
if (ret < 0) {
log_error("Failed to open device");
return;
}
log_info("Device initialized via third-party MCTP library");
}
.so 文件随镜像打包发布你需要确保该 .so 文件最终被安装到目标系统(如 /usr/lib64/ 或组件私有目录),可通过 CMake 的 install() 指令实现:
install(FILES ${PROJECT_SOURCE_DIR}/vendor/third_party_device/lib/libdevice_api.so
DESTINATION ${APP_INSTALL_DIR}/lib)
或在 manifest.yml 中声明为组件资源。
若上层是 Lua 编写的服务,可通过 Luawrap 机制 将 C 接口暴露给 Lua:
// l_device_wrapper.c
#include <lua.h>
#include "device_api.h"
static int l_device_open(lua_State *L) {
const char* dev_path = luaL_checkstring(L, 1);
int ret = device_open(dev_path);
lua_pushinteger(L, ret);
return 1;
}
static const struct luaL_Reg device_lib[] = {
{"open", l_device_open},
{NULL, NULL}
};
int luaopen_device_api(lua_State *L) {
luaL_newlib(L, device_lib);
return 1;
}
编译为 device_api.so 并放入 /usr/lib64 或 $LUA_CPATH,即可在 Lua 中使用:
local device = require("device_api")
device.open("/dev/mctp0")
.so 库是否需要针对当前 BMC 进行适配?这取决于设备方 .so 库的 抽象层级 和 对底层协议栈的依赖程度。以下是关键判断点:
.so 是否依赖 MCTP 协议的具体实现?如果设备厂商提供的 .so 已经封装了 完整的 MCTP over PCIe 逻辑,包括:
那么该库本质上是 高层应用接口代理,你只需调用其 API 即可,不需要修改。
示例参考:
MCTP_LIB提供了从 BDF 到物理地址的转换函数(见 KG 关系BDF -> MCTP_LIB)。Bmc Kepler Systems Mctp MctpBinding Pcie要求在service.json中启用 PCIe Binding 功能(见 KG)。Evan_shenf曾提问如何实现 MCTP over PCIe 适配,回答指向network_adapter仓库的hardware_config目录(见 DC#4),说明协议绑定需框架支持。
.so 依赖特定 MCTP 实现或内核模块可能存在如下问题:
| 问题 | 原因 | 解决方案 |
|---|---|---|
.so 内部调用了 libmctp.so 的函数 |
依赖 BMC 的 MCTP 协议栈 | 确保 libmctp.so 已存在且版本兼容 |
使用特定 /dev/mctpX 节点 |
依赖内核 MCTP 驱动或仿真机制 | 检查 QEMU 或物理平台是否支持 |
| 依赖特定 PCIe 插槽编号或 BDF | 硬编码设备位置 | 改为动态发现机制(如通过 D-Bus 获取对象路径) |
建议:要求设备厂商尽可能提供 基于抽象句柄或 D-Bus 路径的接口,而非固定设备路径。
| 场景 | 是否需要适配 | 说明 |
|---|---|---|
.so 是纯用户态库,仅通过标准 MCTP 接口通信 |
直接集成即可使用 | |
.so 依赖未提供的底层库(如 libmctp.so) |
添加 Conan 依赖项 | |
.so 假设运行在特定硬件拓扑下 |
使用 Skynet/D-Bus 动态获取设备信息 | |
| 需要在 QEMU 中仿真该设备 | 在 manifest 中定义 PCIe 卡配置,加载固件(如 0x02_0x9700_mctp_BF3.bin) |
参考:类似 MCTP PCIe 设备可通过
network_adapter/hardware_config定义协议配置(见 DC#4)
标准化集成方式
.so 和 .h 打包为独立的 Conan 包(如 third_party_device/1.0@vendor/stable)避免硬编码路径和地址
busctl tree bmc.kepler支持仿真环境适配
.bin 固件文件(如 0x02_0x9700_mctp_BF3.bin),放置于 pciecard/ 目录日志与调试机制
framework.log 统一输出(见 adapter.c 日志路径)| 步骤 | 操作项 |
|---|---|
| 1 | 创建 vendor/ 目录存放 .h 和 .so |
| 2 | 修改 CMakeLists.txt 引入头文件和链接库 |
| 3 | 确保 .so 被复制到最终镜像的 /usr/lib64 或组件目录 |
| 4 | 编写 C/Lua 封装代码调用 API |
| 5 | 检查依赖:是否需 libmctp.so, MCTP_LIB, 或特定 PCIe 支持 |
| 6 | 若用于 QEMU:在 manifest 中配置 PCIe 卡和固件路径 |
| 7 | (推荐)将第三方库打包为 Conan 组件,提升复用性和版本管理能力 |
通过以上流程,你可以成功将第三方库集成进 OpenUBMC 组件,并实现 MCTP over PCIe 设备的适配。只要接口抽象得当、依赖清晰、路径可配置,就不需要对 .so 本身做修改,即可实现“即插即用”的集成效果。
集成 so通用的作法一是构建时链接、二是运行时dlopen加载,分别实现方案:
那我新建个组件,把so和.h文件放在组件里面,然后组件内部调用库文件的接口实现监控功能的话,用dlopen的方式应该更合适吧?
既然使用了mctp over pcie的协议,管理的对象应该是网卡、Raid卡或者Nvme盘吧?
这种部件管理在社区已经有组件了,优先考虑在已有组件内补充能力
如果在lua组件中使用这个so,需要通过dlopen的方式打开库后,使用luac库对so提供的的API封装下,以便在lua中使用,整体使用示意图如下(假设该so提供了send和recv方法):
当前这个库是第三方的,对方不能提供源码考虑在openUBMC的环境上交叉编译后提供,因为该库底层涉及到mctp_over_pcie,请问下对方按照论坛安装好编译环境后怎样才能编译出包含mctp over pcie能力的库文件,是否编译参数新增-lmctp即可?
需要先明确这个库的功能才能给出给出使用建议
提供下这个库的具体能力,以及使用方法
提供的功能比如:
使用方法当前预计如下:
1. 实现单独的组件用lua代码调用.so库(该so库是C++编码)提供的接口去获取信息和进行配置
这个还是不够详细,结合之前的信息:
如果so.中提供了一个getPCIeSwTemp的方法,具体使用这个库的能力的时候,这个库使用方式是怎样的呢?
这个库是否具备MCTP协议的解析能力?在通过PCIe总线发送出去需要给它提供一个什么样的输入?
如果它自身具备协议的解析能力,现在需要的只是通过PCIe总线把MCTP报文发送出去能力,这种场景要结合库的使用说明,把调用芯片PCIe总线驱动能力传递给这个库(需要根据库的要求,把驱动的能力做个封装);
如果这个库不具备解析MCTP协议的能力,只是基于mctp over pcie发送自己的数据,这种场景需要把调用库获得的数据帧,通过mctpd组件的发送出去;
当前提供的信息太少,需要有这个库更详细的信息,才能提供更多指导