当前位置: 首页
编程语言
c++如何读取Linux内核生成的Device Tree二进制流【深度】

c++如何读取Linux内核生成的Device Tree二进制流【深度】

热心网友 时间:2026-05-06
转载

C++如何读取Linux内核生成的Device Tree二进制流【深度】 Linux用户态如何解析内核加载的dtb文件 Linux内核在启动过程中会加载并解析dtb(设备树二进制)文件,将其转换为内部数据结构(如struct device_node)。一个关键限制是:**用户态程序无法直接访问内核内

C++如何读取Linux内核生成的Device Tree二进制流【深度】

c++如何读取Linux内核生成的Device Tree二进制流【深度】

Linux用户态如何解析内核加载的dtb文件

Linux内核在启动过程中会加载并解析dtb(设备树二进制)文件,将其转换为内部数据结构(如struct device_node)。一个关键限制是:**用户态程序无法直接访问内核内存中的这些数据**。因此,若要在用户空间获取设备树信息,必须采用替代方案。主要有两种途径:一是直接读取启动时传入的原始dtb二进制文件;二是利用内核提供的标准接口——/proc/device-tree伪文件系统。

常见的错误做法是尝试使用mmap映射/sys/firmware/devicetree/base/proc/device-tree下的文件。这并不可行,因为这些是特殊的只读文件,没有传统意义上的文件长度(使用stat()查询时st_size通常返回0)。正确的方法是使用read()系统调用来读取内容。

  • /proc/device-tree是推荐方案:它以目录树的形式直观地呈现所有设备树节点和属性。你无需手动解析二进制格式,直接进行文件操作即可,且兼容性良好(主流内核版本>=3.10均支持)。
  • 若确实需要原始dtb文件(例如用于签名验证或离线分析),则需确认启动环境中是否保留了该文件。它可能位于U-Boot环境变量fdt_addr_r指向的内存地址,也可能被打包在initramfs中(例如/dtb路径下)。
  • 尽量避免依赖/sys/firmware/devicetree/base:在某些ARM64平台上该路径可能不可见,且部分Linux发行版默认不会挂载它。

使用C++递归遍历/proc/device-tree提取节点信息

这是最轻量且最可靠的方法。其逻辑非常直观:/proc/device-tree下的每个子目录对应设备树中的一个节点(device node);而目录中的每个普通文件则对应一个属性(property),文件内容即为该属性的值(注意:内容可能包含'\0'字符,因此必须使用read(),而非fgets等字符串函数)。

实现时需注意以下几个要点:

立即学习“C++免费学习笔记(深入)”;

  • 使用opendir()readdir()遍历目录,注意跳过“.”和“..”这两个特殊条目。
  • 对每个条目调用stat()判断其类型:如果是目录(S_ISDIR()),则递归进入处理子节点;如果是普通文件(S_ISREG()),则读取其内容作为属性值。
  • 属性值的末尾不会自动附加'\0',其真实长度需通过stat()获取的st_size来确定。对于字符串类属性(如compatible),其内容本身会以'\0'结尾;但对于二进制属性(如reg),它则是原始字节流。
  • 设备树路径可能较深,为输出清晰,建议使用栈结构或递归来控制缩进显示,避免在代码中硬编码层级限制。

以下是一个简单的代码片段,演示如何读取/proc/device-tree/cpus/cpu@0/compatible属性:

int fd = open("/proc/device-tree/cpus/cpu@0/compatible", O_RDONLY);
struct stat st;
fstat(fd, &st);
std::vector buf(st.st_size);
read(fd, buf.data(), st.st_size);
// 此时,buf[0]...buf[st.st_size-1] 就是原始的属性值字节
close(fd);

使用libfdt解析原始dtb文件(需链接libfdt库)

当必须处理原始dtb二进制文件时(例如从Flash存储直接dump,或需与内核启动参数进行一致性校验),libfdt库便成为事实上的标准工具。它被dtc(设备树编译器)、u-boot等广泛使用,头文件为,所有函数均以fdt_为前缀。

典型的解析流程如下:

  • 首先,使用fdt_open_into()fdt_load()等函数,将完整的dtb文件加载到内存中。需特别注意:提供的dtb数据必须是完整且未被截断的二进制流。
  • 接着,可使用fdt_first_subnode()fdt_next_subnode()这对函数组合来遍历设备树的子节点。
  • 读取属性则使用fdt_getprop()函数。它返回一个指向dtb内部缓冲区的指针,**该指针绝对不可手动free,其生命周期完全依赖于fdt blob本身的有效性**。属性的实际长度会通过一个输出参数(lenp)返回。

使用libfdt时,有几个容易出错的地方:

  • 在进行任何其他操作之前,必须先调用fdt_check_header()来校验dtb头的合法性,否则非法dtb文件很可能导致程序段错误(Segmentation Fault)。
  • fdt结构体本身不管理内存,因此承载dtb数据的缓冲区在整个使用周期内都必须保持有效,不能是栈上的临时变量,也不能被realloc等操作移动。
  • 若在多线程环境下使用,需自行加锁,因为libfdt本身并非线程安全,同一fdt实例不支持并发访问。

为何不推荐使用libdevicetree或自行编写解析器

或许有人会问,是否存在其他库,或者是否可以自行编写解析器?通常不建议这样做。

libdevicetree这类非主流库往往缺乏持续维护,API可能不稳定。而自行编写解析器风险极高。dtb的二进制格式包含魔数(magic number)、总长度、结构体偏移量、字符串表偏移量等多个字段,且存在版本差异(如v17/v18)、对齐要求(通常为8字节)以及复杂的字符串表引用机制。即便跳过严格校验,仅想正确识别节点和属性的边界,也极易发生数组越界读取错误。

在实际开发中,大约95%的需求通过/proc/device-tree接口即可完美解决。剩余的5%场景,如bootloader调试或固件签名校验,才是libfdt的用武之地。若非要绕过这两条成熟路径,很可能在自行实现的fdt_next_tag()循环中陷入困境,或读取到乱码数据。

归根结底,真正的挑战并非“如何读取数据”这一动作,而是明确所需数据究竟位于哪一层:是启动时传给内核的原始硬件描述,还是内核解析后生成的运行时视图,亦或是驱动实际看到的platform_device资源?这三者的语义截然不同,绝不能混为一谈。

来源:https://www.php.cn/faq/2320694.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
IDEA中SpringBoot项目热部署实现指南

IDEA中SpringBoot项目热部署实现指南

Springboot项目在IDEA中实现热部署需依次完成:开启自动编译(静态与动态编译)、启用热部署策略、引入spring-boot-devtools依赖、关闭浏览器缓存,最后启动测试即可生效,省去手动重启时间,大幅提升开发效率。

时间:2026-07-11 06:47
Java实现Excel转JSON的代码详解

Java实现Excel转JSON的代码详解

使用Java结合FreeSpire XLS库可自动将Excel转为JSON,通过读取工作表并映射为键值对,高效支持数据迁移、报表导出与系统对接,大幅提升效率并消除手动录入错误。

时间:2026-07-11 06:47
Golang高效布谷鸟过滤器多字符集字符串过滤

Golang高效布谷鸟过滤器多字符集字符串过滤

布谷鸟过滤器支持删除操作,通过指纹截断与双哈希定位实现多字符集高效过滤。指纹截断需采用fnv64a或xxhash快速哈希并取低8位,桶索引使用独立双哈希避免假阳性。并发安全需以固定数组配合sync atomic实现。

时间:2026-07-11 06:47
Java使用Poi-tl按Word模板生成动态表格

Java使用Poi-tl按Word模板生成动态表格

Poi-tl是Word导出工具,文档周全,支持多级合并表头生成。通过{{text}}、{{?var}}、{{ table}}标签处理模板,传入TableRenderData对象即可动态渲染表格。示例展示用户信息表格生成,并提供工具类消除表格首行缩进,确保格式正确。

时间:2026-07-11 06:47
Go语言微服务集成Swagger生成交互式API文档完整教程

Go语言微服务集成Swagger生成交互式API文档完整教程

在Go微服务中集成Swagger常见四大问题:swaginit初始化失败需确保存在packagemain及注释;SwaggerUI加载失败因路由映射错误或未导入docs;@Param注解必须严格遵循格式;部署后接口文档显示localhost因硬编码host,应删除或通过环境变量动态注入。

时间:2026-07-11 06:47
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 热门数据榜