container_of()宏在操作内核标准链表时很有用,也是内核提供的标准方法之一,其他的大多数链表操作都依赖这个宏.
这个宏用于获得一个结构(成员)的父结构体的入口地址.
因为C语言在编译的时候,结构体的地址就由ABI确定下来了, 这才有了下面的实现:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/* type:父结构体的类型
* member:子结构体在父结构体中的域名
* ptr:指向member的指针
*/
#define container_of(ptr, type, member) ({\
const typeof((type *)0)->member) * __mptr = (ptr);\
(type *)((char *)__mptr - offsetof(type, member));})分析如下:
1>检查结构+存放member指针:
const typeof((type *)0)->member) * __mptr = (ptr);假设从0开始存放的是type结构体
获取member的类型
定义一个member类型的指针__mptr, 并把ptr赋值给他(提前知道的)
这一句同时也检查了,type结构体中是否真的包含member域
2>计算member在type结构体中的偏移:
((size_t) &((TYPE *)0)->MEMBER)假设0地址存放了一个TYPE类型的结构体
那么MEMBER的地址就是MEMBER在TYPE结构体中的偏移
3>得到父结构的入口地址, 并以"(type *)"返回:
(type *)((char *)__mptr - offsetof(type, member));__mptr的地址减去它在父结构体中的偏移,就是父结构的入口地址了.
本文详细介绍了container_of()宏的工作原理及其在内核标准链表操作中的应用。该宏能够根据成员指针找到对应的结构体变量,对于链表操作非常重要。
225

被折叠的 条评论
为什么被折叠?



