阅读过linux内核源代码的朋友一定见过container_of宏,container_of用来根据成员变量查找所在基结构体的地址,听起来似乎有点绕,通过下面的几张图和分析就可以比较轻松的理解它的工作原理了。
有一个结构体定义如下:
struct container_type {
...
member_type member; //member_type可以为任何类型
...
};
比如我们这样使用container_of宏:
struct container_type * container = container_of(ptr, container_type, member);
它所表达的意思就是:
member是container结构体的一个成员现在我们知道member的地址ptr通过container_of宏我们就能通过ptr找到container的地址。
通过阅读内核源代码我们可以找到container_of宏的定义:
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
其中offsetof宏的定义为:
#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER)
将0地址强转为TYPE类型指针访问MEMBER成员,再使用&获得MEMBER成员地址即可计算出MEMBER成员在此结构体中的偏移量:
*typeof(((type )0)->member) * __mptr实际上是定义了一个指向member_type类型的指针变量将ptr赋值给这个变量可以获得ptr的地址,(type *)( (char *)__mptr - offsetof(type,member) )最终计算的到container的地址。