linux 内核 container_of() 宏函数 原理详解
container_of() 宏函数源码:
/**
* container_of - cast a member of a structure out to the containing structure
* @ptr: the pointer to the member.
* @type: the type of the container struct this is embedded in.
* @member: the name of the member within the struct.
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
函数作用:
根据某结构体任意一个成员首地址,获得整个结构体变量的首地址。
原理:
某结构体的任意一个成员的相对地址 减去 该成员在该结构体中的绝对偏移 就是该结构体的相对首地址
实例:
struct TEST
{
int a;
char b;
float c;
};
该结构体的内存分配如下图:
struct TEST mTEST={10,'F',12.12};
char *pB=&mTEST.b;
假如pB地址等于0xAABBCC04,根据内存分配推断mTEST的首地址应该为:0xAABBCC00
那么container_of()如何根据pB变量获得mTEST的首地址呢?
步骤如下:
1.利用GNU C标准中的 typeof 关键字,根据结构体struct TEST的成员b,定义一个和b同类型的临时变量指针用来存储输入ptr.
const typeof( ((struct TEST *)0)->b ) *__mptr = (ptr);
2.利用offsetof()获得成员变量b在结构体struct TEST中的绝对偏移量=4,而__mptr=0xAABBCC04,所以获得mTEST的首地址=0xAABBCC00
和推断一样。为什么用(char *)强制类型转换__mptr,是为了让指针__mptr按一个字节一个字节偏移,要不然会根据__mptr数据类型进行偏
移,算出来的地址就不对了。
(struct TEST *)( (char *)__mptr - offsetof(struct TEST,b) );