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) );

你可能感兴趣的:(linux 内核 container_of() 宏函数 原理详解)