Linux 设备树: of_property_match_string 的用法与工作原理

前言

  • 当前新版本的 Linux 内核 设备驱动框架,与设备树(Device Tree)结合密切,整体 设备树的设备驱动框架,比较的庞大,但又非常的经典。

  • 一个个的 设备树解析函数,都是前人【智慧】的结晶,了解 设备树的实现,了解设备树的解析,对Linux 设备驱动开发非常有利,并且可以大大提高开发编码能力

  • 虽然Linux 内核庞大、开源,但是Linux 内核各个模块的实现都是经典,非常适合学习深造

设备树节点与设备树属性

  • 通过 include\linux\of.h 可以获取 设备树节点 struct device_node 与设备树节点属性 struct property 的定义

  • 这里需要特别了解 设备树节点属性:属性name = 属性value,属性value 可能是一个字符串的列表,比如

	i2c1: i2c@fea90000 {compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";reg = <0x0 0xfea90000 0x0 0x1000>;clocks = <&cru CLK_I2C1>, <&cru PCLK_I2C1>;clock-names = "i2c", "pclk";interrupts = <GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>;pinctrl-names = "default";pinctrl-0 = <&i2c1m0_xfer>;resets = <&cru SRST_I2C1>, <&cru SRST_P_I2C1>;reset-names = "i2c", "apb";#address-cells = <1>;#size-cells = <0>;status = "disabled";};
  • 这里 compatibleclock-names reset-names 都有两个 属性值,比如 reset-names = "i2c", "apb";

  • 这里需要确认 reset-names = "i2c", "apb"; 这种 多个属性值的具体 内存储存方式,用于理解如何解析这样的设备树属性,比如分别获取其中的属性,也就是 "i2c", "apb" ,分别得到 "i2c""apb"

property 的 dtb 存储方式

  • 可能大家认为 reset-names = "i2c", "apb"; 在 dtb 中就是 这样的字符串存储,其实 dtb 的生成,有 dtc 的一套复杂的规则决定,这里 属性 name 可能只是一个索引,作为公用的字符串,而属性值如果是 字符串列表(多个字符串),比如 "i2c", "apb",引号不需要,并且 中间的分隔符是 \0,而不是 逗号 ,

  • 这样拆解字符串列表,就不再是以 逗号分隔,而是 字符串结束符 \0 进行分隔,这就需要获取整个字符串的长度【字节数】,这个 设备树属性 的 长度是 struct property 中的 int length; 成员

struct property {char	*name;int	length;   /* 属性 value 的长度(字节数) */void	*value;struct property *next;
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)unsigned long _flags;
#endif
#if defined(CONFIG_OF_PROMTREE)unsigned int unique_id;
#endif
#if defined(CONFIG_OF_KOBJ)struct bin_attribute attr;
#endif
};

在这里插入图片描述

在这里插入图片描述

of_property_match_string 解析

  • 明白了设备树 属性值(property -> value)字符串列表的储存方式后,解析起来就明白多了,这里有个字符串列表 【index】索引的概念,比如第一个,第二个字符串

  • Linux 内核 drivers\of\property.cof_property_match_string 的实现代码如下

/*** of_property_match_string() - Find string in a list and return index* @np: pointer to node containing string list property* @propname: string list property name* @string: pointer to string to search for in string list** This function searches a string list property and returns the index* of a specific string value.*/
int of_property_match_string(const struct device_node *np, const char *propname,const char *string)
{const struct property *prop = of_find_property(np, propname, NULL);size_t l;int i;const char *p, *end;if (!prop)return -EINVAL;if (!prop->value)return -ENODATA;p = prop->value;end = p + prop->length;for (i = 0; p < end; i++, p += l) {l = strnlen(p, end - p) + 1;if (p + l > end)return -EILSEQ;pr_debug("comparing %s with %s\n", string, p);if (strcmp(string, p) == 0)return i; /* Found it; return index */}return -ENODATA;
}
  • 这里入参: 设备树节点,设备树属性 name,就可以查找这个设备树属性 property。

  • 查找到设备树属性 property不是目的,目的就是 查找 设备树属性值 是否匹配,给定一个字符串,是否存在于 字符串列表中,返回字符串列表的索引 index

  • 举个例子: reset-names = "i2c", "apb";,这里查找 "apb" 是否存在,这里存在,就是返回了 index,比如是 1(索引以 0 作为起始)

  • 这里有个经典的字符串列表匹配的算法,就是 通过 总长度,获取整个字符串列表的结束地址,

  • prop->length 就是这个设备树属性 value,也就是 字符串列表的总长度(字节数)

	p = prop->value;end = p + prop->length;
  • 利用了 字符串操作函数都是以 NULL(\0) 作为结束,因此通过获取 单个字符串的 长度,利用指针的加减法(地址加减),就可以逐个判断分隔出来的 单个字符是否匹配

  • 这里 strnlen 用的比较的经典,获取到的其实就是第一次 遇到 字符串结束符 NULL(\0)之前的长度。

小结

  • 这个 of_property_match_string 实现原理比较的经典,当然与 设备树节点属性值的存储有关系,也就是 属性值是字符串列表时,字符串列表的分隔符是 【NULL 或者 \0】,这用于字符串列表的拆解

  • 有些设备树属性确实有多个属性值,有的是数值型的,有的是字符串列表型的,需要解析匹配并获取 匹配值的 索引值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/571242.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux实践室】Linux用户管理实战指南:用户密码管理操作详解

&#x1f308;个人主页&#xff1a;聆风吟_ &#x1f525;系列专栏&#xff1a;Linux实践室、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️任务描述二. ⛳️相关知识2.1 &#x1f514;用户密码存放地及方式2.2 &#x1f514;使用…

Windows上实现iOS APP自动化测试:tidevice + WDA + airtest!

环境准备 本文使用的环境如下&#xff1a; Python 3.7.6&#xff0c;Python版本需要3.6 tidevice0.4.14 WebDriverAgent airtest1.2.2 iOS 设备&#xff1a;iPhone12 Windows系统版本&#xff1a;Windows 10 家庭中文版 使用USB连接设备&#xff0c;检测tidevice是否安…

vue项目使用eletron将打包成桌面应用(.exe)

vue项目使用eletron将打包成桌面应用(.exe) 1.前期准备 两个项目&#xff1a; 1、自己用vue cli创建的项目 2、第二个是去gitee将案例clone下来 案例地址 https://gitee.com/qingplus/electron-quick-start.git 2、测试案例是否可以正常运行 # 进入项目 cd electron-quick-…

python初级2条件与循环笔记

两个课堂小练习&#xff1a; 1、(计算圆柱体的体积) 编写一个读取圆柱的半径和高并利用公式计算圆柱体底面积和体积的程序 iimport math reval(input("enter the r")) heval(input("enter the h")) arear*r*math.pi print("the area ",area,…

韦东山-数码相框(1)

做工程的步骤 弄清需求设计框架编写代码测试 项目需求 上电&#xff0c;LCD显示一副图片&#xff1b; 然后根据默认配置&#xff0c;决定停留还是自动显示下一副&#xff1b; 点击一下&#xff0c;出现对话框&#xff0c;选择手动显示或者自动显示&#xff1b; 根据手势的…

perf出现SIGBUS的coredump

coredump信息 (gdb) bt full #0 0x000055c37fa62c00 in perf_evsel__parse_sample (evsel0x55c381223b00, event0x7f144843ab30, data0x7ffcbbcf6540) at util/evsel.c:1939 type <optimized out> swapped <optimized out> array <optimized out> ma…

MySQL使用教程:数据库、表操作

目录 1. 免密码登录MySQL1.1 免密码配置1.2 登录选项介绍 2. MySQL基础配置&#xff1a;my.cnf3. 开机自启动设置&#xff08;可选设置&#xff09;4. 查看存储引擎5. 查看系统的编码规则和校验规则6. 数据库的操作6.1 查看数据库6.2 创建数据库 create database6.3 删除数据库…

正信法律:朋友生病借了钱不认我该怎么办

当朋友生病急需帮助时&#xff0c;伸出援手是人之常情。但若借款之后对方迟迟不还款&#xff0c;甚至出现不承认借款的情况&#xff0c;这无疑会让人陷入两难的境地。面对这样的困境&#xff0c;我们需要保持冷静&#xff0c;理性地分析情况&#xff0c;并采取适当的措施来解决…

畅捷通T+ Ufida.T.DI.UIP.RRA.RRATableController 远程命令执行漏洞

一、漏洞信息 漏洞名称&#xff1a;畅捷通T Ufida.T.DI.UIP.RRA.RRATableController 远程命令执行漏洞 漏洞类别&#xff1a;远程命令执行漏洞 风险等级&#xff1a;高危 二、漏洞描述 畅捷通TPlus适用于异地多组织、多机构对企业财务汇总的管理需求&#xff1b;全面支持企…

基于springboot+vue的乌鲁木齐南山冰雪旅游服务网

作者主页&#xff1a;Java码库 主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】&#xff1a;Java 【框架】&#xff1a;spring…

SAP Fiori开发中的JavaScript基础知识4 - 在BAS中开发和调试JavaScript代码

1 背景 SAP Business Application Studio(BAS) 内置了对Node.js运行时的调试支持&#xff0c;可以调试JavaScript、TypeScript或任何其他被编译成JavaScript的语言。 我们在学习JavaScript的过程中&#xff0c;可以直接使用SAP BAS开发和调试JavaScript代码。 2 开发代码 需…

Python(Socket) +Unreal(HTTP)

Python&#xff08;Socket&#xff09; Unreal&#xff08;HTTP&#xff09; python&#xff08;Socket&#xff09;:UE&#xff1a;Post请求并发送本机IP 上班咯&#xff0c;好久没记笔记了。。。 局域网 UE的apk&#xff0c;请求Python的Socket 跑起Socket &#xff0c;UE发 …