Devmon 项目概览

对照源码刷新日期:2026-08-18

组件版本:1.2.88(mds/service.json / CHANGELOG)

仓库:https://gitcode.com/openUBMC/devmon

所属 SIG:openUBMC Hardware Management SIG

许可证:Mulan PSL v2

本文只描述 devmon 仓库当前代码 的职责与目录特性。构建、bingo 测试与环境准备以仓库根目录 README.md 为准;本文不替代构建指导。


1. 项目介绍

Devmon(Device Monitor) 是 openUBMC 的设备监控与南向设备管理服务。它不实现具体网卡/GPU 驱动,而是提供:

  1. CSR(.sr 自描述文件)解析与对象实例化:把机型/部件的配置状态寄存器描述变成引擎对象树。
  2. 驱动 ABI 与动态加载:按 driver_abi.h 用 dlopen 加载 component_drivers 产出的 .so(C 语言风格函数表,C++ 侧封装为 device_driver)。
  3. 对象组 / 拓扑 / 热插拔:按 Position 管理设备生命周期,对外暴露 D-Bus 接口 bmc.dev(AddDevice / RemoveDevice)。
  4. 可选三层架构(unidev):同一进程内拆成 devmon_service、hwproxy_service、discovery_service 三个服务,分别管业务设备、硬件代理(Accessor/Scanner)、CSR 发现。

与旧版仓库的关键差异(读旧文档时务必先看这一段):

旧概览里的路径 当前代码
本仓 plugins/(PCIe 网卡等) 已迁出,由独立仓 component_drivers 提供;本仓通过 Meson wrap / Conan 依赖拉取
本仓 libraries/(MCTP / NCSI / IMU) 不在本仓
本仓 gen/(代码生成) 不在本仓;接口代码由 bingo gen / 其它仓生成
核心实现在 src/device/ 已拆到 libs/common、libs/devmon,src/ 只剩进程入口 main.cpp

C 对照:可以把整个进程想成一个常驻 daemon。src/main.cpp 相当于 C 的 main();libs/*.so 相当于拆出去的共享库;namespace devmon { class X; } 相当于 C 里带前缀的结构体 + 一组操作函数,只是成员函数写在类型里面。


2. 运行架构(两种 Linux 形态 + Zephyr)

构建选项 -Dunidev=(Conan 选项 unidev,mds/service.json 默认为 false)决定进程内注册哪些服务。src/main.cpp 启动时会打日志 architecture mode: three-layer | single。

2.1 单层(默认,unidev=false)

只注册 devmon_service(D-Bus 名 bmc.kepler.devmon)。拓扑发现由 topology_discovery 去订阅外部 bmc.kepler.hwdiscovery。驱动 ABI 强制 abi_v2。

配置模板:config.single.json.in → 安装为 /opt/bmc/apps/devmon/config.json。

2.2 三层 / unidev(unidev=true)

同一 devmon 进程内注册三个服务(启动顺序与就绪门闩见 CHANGELOG 1.2.73):

服务类 D-Bus 名 根对象 职责
hwproxy_service bmc.kepler.hwproxy HwProxy(/bmc/kepler) Accessor / Scanner / SmcDfxInfo 及防抖对象(Median/MidAvg/Cont/ContBin)
discovery_service bmc.kepler.hwdiscovery HwDiscoveryRoot(/bmc/kepler/hwdiscovery) CSR 全量发现、设备加载状态机、Connector
devmon_service bmc.kepler.devmon Devmon(/bmc/dev) CSR2 业务设备与 DevTopology

FormatVersion 路由(libs/common/include/devmon-common/dev_discovery_constants.h):

  • < 5.00 → CSR1 / abi_v1 → 拓扑挂到 HwProxy,发现走 hwdiscovery
  • ≥ 5.00(缺省也是 5.00)→ CSR2 / abi_v2 → 拓扑挂到 DevTopology

配置模板:config.three-layer.json.in。发现服务会等 service_readiness 里 应用就绪 + hwproxy 就绪 后再跑 CSR 全量发现,避免对象注册到错误服务。

2.3 Zephyr 常驻(zephyr/,Linux meson 不编译)

小型化镜像用 CONFIG_DEVMON=y 把 libs/common + libs/devmon 编进静态库,入口是 SYS_INIT(devmon_init, APPLICATION, 60)。固定单层、无 dlopen、无 topology_discovery、无 hwdiscovery/hwproxy。驱动在 SYS_INIT 期静态注册。

flowchart LR
    subgraph linux["Linux 进程 devmon"]
        main["src/main.cpp"]
        main --> app["mc::app::application"]
        app --> S["devmon_service"]
        app -.->|"仅 unidev"| P["hwproxy_service"]
        app -.->|"仅 unidev"| D["discovery_service"]
    end
    S --> so["libdevmon.so + libdevmon-common.so"]
    P -.-> hp["libhwproxy.so"]
    D -.-> hd["libhwdiscovery.so"]
    so --> drv["component_drivers 的 libdev_*.so"]

3. 目录结构

3.1 顶级目录

目录/文件 关键特性(当前代码)
libs/ 真正的核心源码。产出 libdevmon-common、libdevmon;unidev 时再产出 libhwdiscovery、libhwproxy
src/ 进程入口:main.cpp 注册服务、malloc_trim 后台线程、就绪门闩
include/ 对外 C ABI:include/devmon/driver_abi.h(驱动 .so 必须实现的函数表)
mds/ bingo/MDS 元数据:model.json(Chip/Scanner 方法)、service.json(组件版本 1.2.88、unidev 选项、Conan 依赖)
tests/ 共享测试夹具与数据:main.cpp、tests_data/、Lua stub。GTest 目标已迁到 libs/*/tests;根目录 tests/meson.build 未被 顶层 meson.build subdir()
libs/*/tests/ 当前实际 UT:common_test、devmon_test;-Dunidev=true 时再编 hwdiscovery_test、hwproxy_test
test/ 遗留 Lua 包装:test/unit/test.lua,用于定位 devmon_test 可执行文件;meson 默认不走这里
docs/ 特性说明(本文档系列)。构建流程仍以根 README.md 为准
scripts/ 本地 meson 智能构建:smart_build.sh、压测循环 run_tests_loop.sh
dist/ 产品 rootfs:systemd unit(MemoryMax=150M,ExecStart=/opt/bmc/apps/devmon/devmon)
stub/ 无 securec 时的 securec.h 打桩,仅 enable_conan_compile=false 的本地 meson 使用
subprojects/ Meson wrap-git:libmcpp.wrap、component_drivers.wrap(本地构建副本,改驱动请改上游仓)
zephyr/ Zephyr module 胶水:Kconfig / CMakeLists.txt / devmon_sys_init.cpp
builddir/ meson 输出(gitignore)。驱动测试库路径在测试态为 builddir/test_drvlib/{chip,bus}
.devcontainer/ VS Code 远程容器,镜像 ubuntu:24.04.2_26.06
.vscode/ 编辑器配置

构建产物目录 temp/、builddir/ 不入库。

3.2 核心文件

文件 描述
meson.build 顶层构建:C++17、DEVMON_ENABLE_UNIDEV、chip/bus 驱动路径、subdir(libs/*)、安装 systemd 与 config.json
meson_options.txt meson_build / enable_conan_compile / tests / unidev / enable_coverage / install_inc_dir
conanfile.py / conanbase.py Conan2 包定义;选项 asan / gcov / test / enable_luajit / unidev
src/main.cpp 进程入口
config.single.json.in / config.three-layer.json.in 运行时 Application + Service + Logging;安装名为 config.json
whitelist.json 对象重命名白名单前缀(默认 Fan_ / Fans_ / FanType_ / OnePower_),安装到 /opt/bmc/apps/devmon/
design.md 早期设计笔记,部分路径已过时,以本文 + libs/ 源码为准
README.md 构建与 bingo 测试的唯一指导
CHANGELOG 组件变更(当前头版本 1.2.88)
.clang-format / .clang-tidy / .pre-commit-config.yaml 格式、静态检查、提交钩子

4. 详细目录描述

4.1 libs/common/ — 共享内核(libdevmon-common.so)

单层和三层、Linux 和 Zephyr 都链接 这一层。头文件在 include/devmon-common/。

模块 路径 关键特性
架构开关 architecture.h DEVMON_ENABLE_UNIDEV 编译期常量 is_unidev_enabled()
发现常量 dev_discovery_constants.h FormatVersion 阈值 5.00、ABI 解析、直挂对象策略表(Connector→hwdiscovery,Accessor/Scanner/…→hwproxy)
驱动加载 device_driver.h/.cpp dlopen 工厂;按名字 + abi_v1/abi_v2 缓存;记录加载耗时
驱动 ABI driver_abi.h 与 include/devmon/driver_abi.h 同构的 C 函数表:ctor/init/start/stop/dump
CSR 解析 csr_parser.* 任务链(match/rename/…):拆出拓扑对象与直挂服务对象,处理 $ref、同步属性、`
CSR 工具 csr_utils.* / csr_types.* Unit/Connector 反射结构、白名单重命名、变量替换(含 ${Bom})
设备 CSR device/csr.* 按 CSR 创建/注销设备对象、子设备、函数对象 Func_*
设备管理 device/manager.* 单例 device_manager:add_device / remove_device(含子部件级联,且不误卸共享总线)
拓扑 topology/device_topo.* 总线/芯片树、按 FormatVersion 选根对象、SubBuses 一级总线
对象组 object_group.* ObjectGroupRoot /bmc/dev/ObjectGroup;按 Position 的上线屏障
Schema app_schema.* 扫描 app_paths 下各 app 的 mds/schema.json,解析类/属性/接口
全局模型 global_model.* 读 /opt/bmc/conf/global/global.json(可降级找路径)
就绪门闩 service_readiness.* 应用 / hwproxy 就绪标志,供三层发现等待
工具 utils.* 毫秒时间、Connector Position/Unit 解析、构建类型

C 对照:device_driver_factory 是进程级单例(类似 C 里的全局表 + pthread_mutex);MC_REFLECTABLE 给结构体生成元数据,运行时可用字符串读写字段,相当于手写的「字段名 → offsetof」表。

4.2 libs/devmon/ — 设备管理服务(libdevmon.so)

模块 路径 关键特性
服务 devmon.h/.cpp devmon_service:on_configure 加载 schema/global/驱动路径;on_start 注册三棵根对象;on_dump 导出 scanner/accessor/芯片访问/驱动加载 CSV
根对象 devmon_root_object.* 对象名 Devmon,路径 /bmc/dev
根接口 devmon_root_interface.* 接口 bmc.dev:add_device / add_device_with_data / remove_device
拓扑根 topology/root_topo_object.* 对象名 DevTopology,路径 /bmc/dev/topology
拓扑发现 topology/topology_discovery.* 仅单层且非 Zephyr 编译。订阅外部 hwdiscovery,超时生产 60s / 测试 1s

meson.build:unidev 为真时 不编译 topology_discovery.cpp(发现改由本进程 discovery_service 负责)。

4.3 libs/hwdiscovery/ — 发现服务(仅 unidev,libhwdiscovery.so)

模块 关键特性
discovery_service 等应用 + hwproxy 就绪后异步跑发现;超时 60s
discovery/ start_discovery / full_discovery;根对象 HwDiscoveryRoot;KeplerObjectGroupRoot(/bmc/kepler/ObjectGroup)
component/device_loader 顺序任务队列(加/卸载按序号排队,在单条串行执行队列上按到达先后依次执行);分层加载状态机(reserved→csr_merge→csr_parse→object_group→topology→direct_service_objects→commit/rollback);父子 Position 入队避免死锁、在位信号去重、防设备被错误重新加载与无谓重复加载,详见 devmon_device_load_unload_sequencing.md
component/csr_config 机型 / 用户定制 / import / product CSR 路径合并
component/unit_config_manager UnitConfiguration 扁平 uid_map,跨 Position 复用槽位
component/component_utils 部件加载辅助

4.4 libs/hwproxy/ — 硬件代理服务(仅 unidev,libhwproxy.so)

体积很小:根对象 HwProxy + hwproxy_service。职责是挂 Accessor/Scanner 等直挂对象,并 dump 扫描器/访问器/芯片访问/SMC DFX(含最近 10 次)。on_start 置 set_hwproxy_ready(true),发现侧据此放行。

4.5 src/ — 进程入口

只有 main.cpp 与 meson.build。

  • 后台线程每 5 分钟 malloc_trim(0),并 mallopt(M_ARENA_MAX, 1),控制 glibc arena 膨胀。
  • register_service<devmon_service>;DEVMON_ENABLE_UNIDEV 时再注册 hwproxy、discovery。
  • service_readiness::set_application_ready 在 app.start() 成功后置位,退出/异常时清掉。
  • 可执行文件安装到 /opt/bmc/apps/devmon/devmon。

4.6 include/ — 公共 C ABI

仅 include/devmon/driver_abi.h。这是给 C 或 C++ 驱动 .so 的稳定函数表(register_device_driver、device_driver 结构体)。C++ 驱动实现这些函数指针即可被 dlopen;不必懂 mc::engine::object。

4.7 mds/

文件 关键特性
service.json 组件名 devmon,版本 1.2.88;选项 unidev;构建依赖 component_drivers/[>1.1.0];测试依赖 skynet
model.json 暴露 Chip.Read、TraceChip、Scanner.TraceDebounce 等方法元数据,供 mdbctl 等北向工具

4.8 tests/ 与 libs/*/tests/

以 libs/*/tests 为准。 顶层 meson.build 在 build_tests 时:

subdir('libs/common/tests')      → 可执行文件 common_test
subdir('libs/devmon/tests')      → 可执行文件 devmon_test
unidev 时再:
  subdir('libs/hwdiscovery/tests') → hwdiscovery_test
  subdir('libs/hwproxy/tests')     → hwproxy_test

tests/ 仍承担:

内容 作用
main.cpp 被 common/devmon 测试链接的 gtest 入口(覆盖率时 quick_exit 前刷 gcov)
tests_data/ CSR 样例(含 Hi182x/Hi183x PCIe NIC .sr)、各 app 的 schema.json、global.json;构建时复制到 builddir/tests_data
plugins/ 应用层 Lua 插件 UT(5 个 hwproxy Chip 插件),见 tests/plugins/README.md
test_paths.h 测试路径常量
meson.build、test_devmon.cpp、test_utils.cpp、bus/test_i2c.cpp 遗留:根 meson 不再 subdir('tests'),勿当作当前入口

截至 2026-08-17,源码中 TEST* 宏大约:common ~328、devmon ~1040(test_i2c.cpp 因引擎 API 已禁用)、hwdiscovery ~168、hwproxy ~20。默认 unidev=false 的 builddir 只注册 common_test 与 devmon_test。

各 libs/*/tests 与 tests/{device,discovery,topology}/ 的 README 若与上述布局不一致,以 meson 源为准。

4.9 scripts/

脚本 关键特性
smart_build.sh 按 CPU/内存算 ninja -j;ccache;wrap-git 快进;-X 按 wrap 重克隆远端后再叠加 sibling 未提交补丁;setup→compile→install→test;--coverage / --clean
run_tests_loop.sh 循环跑测,用于稳定性

产品构建仍用 bingo build / bingo test -ut -jit(见 README)。

4.10 dist/ / stub/ / subprojects/ / zephyr/ / .devcontainer/

目录 关键特性
dist/user_conf/rootfs/etc/systemd/ devmon.service:依赖 framework.service + dbus.service,MemoryMax=150M,Restart=always
stub/securec.h 本地 meson 无华为 securec 时的兼容头
subprojects/*.wrap libmcpp、component_drivers 从 GitCode main 浅克隆。改子项目代码必须回上游仓
zephyr/ 小型化 SYS_INIT 常驻;与 Linux meson 隔离
.devcontainer/ 官方镜像 swrcn-north-4.myhuaweicloud.com/openubmc/ubuntu:24.04.2_26.06(较 README 中的 24.04.2 更新的 26.06 快照)

5. 项目架构

5.1 对象与服务

热插拔从 bmc.dev.AddDevice 进进程:解析 CSR → dlopen 厂商 so → 把对象挂到拓扑/对象组。三层模式下 FormatVersion 小于 5.00(CSR1)可能先转到 HwDiscoveryRoot(见 §2.2、§5.3)。

下图只画 AddDevice 加载链。实线是默认/CSR2;虚线是仅 unidev 的 CSR1 转发。HwProxy 不在这条链上,见文后对象表。

flowchart TB
    Add(["① busctl AddDevice<br/>.sr + Connector"])

    subgraph entry["② D-Bus 入口"]
        direction LR
        Devmon["②a Devmon<br/>/bmc/dev"]
        HD["②b HwDiscoveryRoot<br/>/bmc/kepler/hwdiscovery"]
    end

    Add --> Devmon
    Add -.->|"仅 unidev · CSR1"| HD

    subgraph parse["③ 解析 / 状态机"]
        direction LR
        CSR["csr_parser<br/>+ device_csr"]
        Loader["device_loader<br/>状态机"]
    end

    Devmon --> CSR
    HD --> Loader

    Factory["④ device_driver_factory<br/>dlopen"]
    CSR --> Factory
    Loader --> Factory

    SO["⑤ component_drivers<br/>libdev_*.so"]
    Factory --> SO

    subgraph mount["⑥ 挂到对象树"]
        direction LR
        Topo["DevTopology<br/>/bmc/dev/topology"]
        OG["ObjectGroupRoot<br/>/bmc/dev/ObjectGroup"]
    end

    CSR --> Topo
    CSR --> OG
根对象 D-Bus 路径 何时存在 在加载链上的角色
Devmon /bmc/dev 始终 ②a 入口,bmc.dev.AddDevice
HwDiscoveryRoot /bmc/kepler/hwdiscovery 仅 unidev ②b CSR1 转发入口
DevTopology /bmc/dev/topology 始终 ⑥ CSR2 拓扑挂载点
ObjectGroupRoot /bmc/dev/ObjectGroup 始终 ⑥ Position 对象组
HwProxy /bmc/kepler 仅 unidev 不在本链;挂 Accessor / Scanner
KeplerObjectGroupRoot /bmc/kepler/ObjectGroup 仅 unidev 不在本链;发现侧对象组

C 对照:mc::engine 对象树 ≈ 一棵挂在 D-Bus 上的结构体森林;device_driver_factory ≈ 进程级 dlopen 缓存表(单例 + mutex)。

5.2 插件与接口(实现已不在本仓)

接口定义仍在 mdb_interface / MDS,C++ 通用接口与厂商 .so 在 component_drivers。devmon 只消费 ABI:

flowchart TD
    A["mdb_interface JSON"] -->|"bingo gen"| B["C++ 接口 / 对象模型<br/>component_drivers"]
    B --> C["厂商驱动 .so<br/>实现 driver_abi"]
    C -->|"dlopen"| D["devmon device_driver_factory"]
    D --> E["引擎对象树 + D-Bus"]
    F["北向 Redfish / IPMI / CLI"] -->|"调用对象属性/方法"| E

5.3 热插拔入口(开发调试)

busctl --user call bmc.kepler.devmon /bmc/dev bmc.dev AddDevice sa{sv} \
  "../tests/tests_data/csr/14140130_19e50222_19e500a1.sr" \
  3 Position i 2 SystemId i 1 Slot i 2

三层模式下 CSR1 可能被根接口转发到 hwdiscovery(见 device_topo / hwdiscovery_root_interface 的 FormatVersion 判断)。


6. 核心技术

技术 在本仓中的用法
C++17 全库语言标准;std::shared_ptr / std::mutex / std::atomic 管理生命周期与并发
mc::engine / mc::app::service 对象树、属性、D-Bus 导出(来自 libmcpp)
MC_OBJECT / MC_INTERFACE / MC_REFLECTABLE 注册对象路径、接口名、可反射字段(C 里没有的「运行时类型信息」宏)
mc::dict / mc::variant 动态 JSON 风格属性(类似 C 的嵌套 hashmap,值类型运行期才确定)
驱动 ABI C 函数表,保证 Lua/C++/静态表多种实现都能加载
FormatVersion + ABI 版本 三层下按 CSR 代际选 abi_v1/abi_v2 驱动文件
Meson + Ninja 本地/Conan 编译;meson_build=true 时 libmcpp 关 SHM,与 UT 的进程内对象表一致
Conan2 产品依赖与 bingo 出包
systemd 产品拉起;内存上限 150M
Zephyr SYS_INIT 小型化无动态加载器形态

共享内存注意:Conan/产品构建定义 MCDBUS_USE_OLD_SHM=1,对象表走跨进程 SHM;本地 meson UT 不定义该宏,与 libmcpp 子工程 use_shm=false 对齐。混用会直接编译失败(模板实参 shm_storage_engine vs local_storage_engine 对不上)。


7. 构建和运行

7.1 系统要求(与 README 对齐,2026-08)

项目 要求
宿主 OS 仅 Ubuntu 24.04 LTS
官方容器镜像 swrcn-north-4.myhuaweicloud.com/openubmc/ubuntu:24.04.2(README);devcontainer 已用 24.04.2_26.06
语言 C++17,Meson + Ninja
基础库 libmcpp、component_drivers、dbus-1、glib-2.0;测试需 gtest
产品工具链 bingo + Conan2(必须走 manifest init.py,禁止手装 conan)

7.2 常用命令

# 产品路径(README)
bingo build --stage=dev
bingo test -ut -jit

# 本地 meson 路径
./scripts/smart_build.sh
./scripts/smart_build.sh --coverage
./scripts/smart_build.sh -X   # 按 wrap 拉最新远端,再叠加 ../libmcpp 等未提交补丁后全量重建
meson setup builddir -Dunidev=true   # 编三层 + hwdiscovery/hwproxy 测试

驱动运行时搜索路径:

  • 生产:/opt/bmc/apps/devmon/drvlib/{chip,bus} 以及配置里的 driver_path(默认 /opt/bmc/drivers/)
  • 测试:builddir/test_drvlib/{chip,bus}

8. 开发指引(本仓边界)

8.1 改设备插件 / 协议栈

不要在 devmon 仓库新建 plugins/。到 component_drivers 实现 driver_abi.h 函数表,再由 bingo/Conan 把 .so 装到驱动目录。本仓 subprojects/component_drivers 只是 wrap 副本。设备 so 分层见 2.1.设备层插件.md。

应用层 Lua 插件(hwproxy.plugins.*/init.lua、PluginRequest)见 2.2.应用层插件.md,不要在设备 so 里重写 has_cmd/run_cmd。插件 UT 方案与原则见 2.3.插件测试方案和原则.md。

8.2 改设备管理 / CSR / 发现

改 libs/common(共享解析与拓扑)、libs/devmon(单层服务)、或 unidev 下的 libs/hwdiscovery / libs/hwproxy。同步补对应 libs/*/tests,不要把新 UT 写进已停用的 tests/meson.build。

8.3 相关文档

文档 内容
2.1.设备层插件.md 设备 so 插件分层设计(实现已在 component_drivers)
2.2.应用层插件.md 应用层 Lua 插件、PluginRequest、C++ 宿主原样跑 Lua 的调用链与缺口
2.3.插件测试方案和原则.md 应用层插件 UT:双入口、替身对齐、测试原则;落地见 tests/plugins/
3.1.device_interfaces.md 设备接口规范
3.2.device_object.md 对象模型与反射
3.3.pcie_nic_card.md PCIe 网卡对象示例
4.protocol.md 协议说明(协议库不在本仓)
5.has.md 硬件访问抽象
6.meson构建说明.md 本地 meson 补充(镜像/依赖以 README 为准)
出包流程.md 三仓联编出包
sfmea-failure-modes.md PCIe 发现 / Connector 生命周期故障模式
特性/详细设计说明书、性能优化方案 需求与方案底稿;目录以本文为准

9. 版本与社区快照(2026-08)

项 值
本组件 1.2.88(2026-08-17:复杂属性变量语法测试补全)
近期架构演进 三层 unidev、CSR1/CSR2 分流、device_loader 层级状态机、SubBuses、Zephyr SYS_INIT、systemd 150M 上限
构建宿主 Ubuntu 24.04.2(devcontainer 快照 26.06)
依赖仓 libmcpp、component_drivers(GitCode openUBMC 组织)
开源许可 Mulan PSL v2