Linux内核中的宏/container_of分析

今天在看平台设备实现的时候,看到to_xxx开头的“函数”。包括在内核中也有很多此类的“函数”,其实他们都是container_of的宏。因为内核是链表和结构体的世界,因此内核中有大量需求要 根据结构体成员获取结构体地址 ,或者根据结构体类型和结构体成员类型获取成员在结构体的偏移
match函数
最后container_of的实现如下:
根据注释可以得到几点信息:container_of的作用是根据结构体成员地址找结构体地址
ptr是指向成员的指针
type是结构体的类型
member是成员的名字
下面来分析一下这到底如何实现。
const typeof( ((type *)0)->member ) *__mptr = (ptr);
这句话实际上仅仅是把ptr的地址传给一个临时的变量__mptr。const表明__mptr不会修改ptr指向的数据,具体就是结构体成员的数据。typeof是扩展关键字,用于获取某个变量的类型,确保menber的类型和传入的ptr指向的数据类型一致。
接下来的重点就是:
((type *)0)->member如何理解?
先来概括一下:用一个指向0地址的指针,获取结构体的成员变量。
看看平时是如何获取一个结构体变量的,首先初始化一个结构体实例a,然后声明一个结构体指针指向这个实例:struct xxx *p = &a;此时 p = a的地址,等价于 (struct xxx *)&a;
再看看(type *)0是不是很像?type就是结构体的类型,0就是某个结构体实例的地址。就是把结构体实例放到0地址嘛!((type *)0)等价于一个指针,这个指针指向0地址,类型是type类型。接下来都水到渠成。
总结一下:const typeof( ((type *)0)->member ) *__mptr = (ptr);仅仅是把传入的ptr地址赋给_mptr临时变量,得到的_mptr是一个绝对地址。假设是20,后面会用到。
(type *)( (char *)__mptr - offsetof(type,member) );})
先看offsetof(type,member) )的实现
offsetof
这里和上面分析的一样,只不过多了一个取地址符号:把结构体实例放到0地址,然后获取成员变量,然后取地址,这时候取出的地址是相对0偏移的地址,也是相对于结构体地址的偏移地址,假设是4.
那么__mptr - offsetof = 20 - 4 = 16 = 结构体地址(绝对地址)。
理解了这个,其他都是一些类型检查,边角料。

贵州首支成体系化的无人机编队用于消防救援中
中国联通成立边缘云创新实验室,自主研发Cube-Edge平台
导光板和手机背盖有什么联系呢?
如何使用手机连接电视机
加密货币能够抵御经济动荡,可提供国际援助和改善全球经济
Linux内核中的宏/container_of分析
英特尔自旋电子学技术获新进展 芯片尺寸可缩小5倍能耗降低至多30倍
电子变压器是什么,它的具体作用是怎样的
苹果正在为iPhone系列手机考虑Siri离线模式可在无网络的情况下使用
行业数据:中国大陆基板封装产线统计
离线硬盘强制上线导致RAID5崩溃的数据恢复
HMS已成全球第三大移动生态系统,目标冲击谷歌的GMS
金银通出售3310D、HP6063B、Chroma63303
ADSL低噪声前置放大接收器的设计
高压侧N沟道MOSFET栅极驱动器的应用
解读腾讯云原生 鹅厂云原生的“新路”与“历承”
荣耀手表评测 精雕细琢的称职生活助理定位精准的腕上运动教练
如何选用玻璃转子流量计
Micro-LED能否挑战LCD和OLED?
疫情催化物联网行业发展,前景巨大