通过实例学习container_of( ), 分步解决2个问题:
1>>求结构体某成员到此结构体起始地址的[绝对距离].
2>>求结构体起始地址.
struct node_st {
int id;
int math;
int phy;
};
struct node_st node1 = {
.id = 1,
.math = 99,
.phy = 88,
};
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1> 解决第<1>个问题:
已知: 结构体类型为 struct node_st, 求phy成员到结构体node1地址的绝对距离??
linux内核解决方法:
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
理解: (unsigned long) &((struct node_st *)0)->phy;
成员 | 地址 |
phy | 0x8 |
math | 0x4 |
id | 0x0 |
这样得到绝对距离为8, 巧妙之处:借用0地址.(0地址巧用还有个NULL)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2> 解决第<2>个问题:
已知:结构体类型为 struct node_st, phy成员及phy成员的地址, 求node1的地址???
内核解决方法:
#define container_of(ptr, type, member) ({ \
const typeof(((type *)0) ->member)*__mptr = (ptr); \ /*疑问?这句多余吗*/
(type *)((char *)__mptr -offsetof(type, member)); })
理解: container_of(&node1.phy, struct node_st, phy)
(struct node_st *) (char *)ptr - 8;
就是:用phy的实际地址(&node1.phy)减去绝对距离(8), 得到node1的地址;
NOTE:
1>> ({ }) 这种风格, 最后一句<;>就是结果.
2>> char *强转目的:按1个字节偏移
?疑问:
这是内核的严谨, 可以判断&member的类型和ptr的类型是否一致!
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
总结:
container_of(ptr, type, member) :
输入3样:
<1>结构体类型type, <2>某一成员member, <3>member成员地址,
输出出结构体地址. 功能强大!!
学习总结内核的代码技巧有益身心健康!!