list.h中宏list_entry宏的解析与应用

本文深入探讨了Linux内核中的list_entry宏及其内部的container_of宏的工作原理。通过对宏定义的逐行解析,文章详细解释了如何通过一个指向结构体成员的指针来获取整个结构体的地址。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

list_enty这个宏算是内核里面比较复杂的宏了。下面就对它的结构进行解析。宏的结构为:

 

这个宏的作用是通过ptr指针获取type的地址,其中ptr是member的指针,member是type结构的成员。

这个宏里面包含另外一个宏,container_of。这个宏位于/linux/kerner.h,它的结构为:

 

这个宏包含两条语句。第一条:const typeof( ((type *)0)->member ) *__mptr = (ptr);首先将0转化成type类型的指针变量(这个指针变量的地址为0×0),然后再引用member成员(对应就是((type *)0)->member ))。注意这里的typeof(x),是返回x的数据类型,那么 typeof( ((type *)0)->member )其实就是返回member成员的数据类型。那么这条语句整体就是将__mptr强制转换成member成员的数据类型,再将ptr的赋给它(ptr本身就是指向member的指针)。第二条语句里面的offsetof也是一个宏,它在/linux/stddef.h中这样定义:

 

((TYPE *)0)->MEMBER)这个其实就是提取TYPE类型中的member成员,那么&((TYPE *)0)->MEMBER)得到member成员的地址,再强制转换成size_t类型(unsigned int)。因为它的结构体地址从0开始定义,所以得到的member成员的地址就是它相对于结构体的偏移地址。再回到contanier_of的第二句话,把得到的member的地址强制转化成char *,(这里不是很理解,借用别人的思路),因为如果member是非char型的变量,比如为int型,并且假设返回值为offset,那么这样直接减去偏移量,实际上__mptr会减去sizeof(int)*offset!这和指针的自加自减运算一样,根据其指向的变量的类型不同而不同。(同意)

接下来,container_of宏的含义就不言而喻了,也就是list_entry宏。

下面是对该宏实现的一个应用实例,以加深理解。

 

运行结果如下:

 

$ ./offset 

address of &stu is=0xbf89bb18

 

addressx of &stu-num=0xbf89bb18 offset of stu->num is=0

 

addressx of &stu-name=0xbf89bb1c offset of stu->name is=4

 

addressx of &stu-sex=0xbf89bb1d offset of stu->sex is=5

 

computing address of &stu using:

address and offset of stu->num=0xbf89bb14

address and offset of stu->name=0xbf89bb17

address and offset of stu->sex=0xbf89bb18

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值