内核中的container_of的实现

来源:互联网 发布:电脑内存优化 编辑:程序博客网 时间:2024/05/16 05:01

1、         功能

Container_of是从一个已知的结构体和其中一个成员及其该成员的指针,返回该结构体的首地址。字面意思:装某某成员的容器的地址。

2、        原型(在linux/kernel.h中定义)

#definecontainer_of(ptr, type, member) ({                     \        const typeof( ((type *)0)->member )*__mptr = (ptr);      \        (type *)( (char *)__mptr - offsetof(type,member) );})

ptr就是成员的指针,type是结构体类型,member是结构体成员。其中的offsetof又是一个宏定义,在linux/stddef.h中定义:

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE*)0)->MEMBER)

offsetof(offset偏移量,意思某某成员在该结构体的偏移量)是为了求结构体中某个成员相对于结构体首地址的偏移量,但现在不知道其首地址,所以用了一个技巧,相当于把结构体移到地址0,这样取出该成员的地址就是相对于结构体首地址的偏移量。这儿有一个注意点,就是在0地址取结构体的成员的地址,这是允许的,因为我们没有取该地址里的值,而是取该地址。(事实上,此处并没有值,所以取值会出现段错误)。另外__mptr指针需转换成char*型,因为指针减去一个数相当于减去该指针类型的那么多个偏移量。

3、        代码验证如下:

#include <stdio.h>#include <stddef.h>struct stu{        char name[20];        int age;        float score;};int main(void){        struct stu xiaoyuan = {"xiaoyuan", 32, 56.4};        printf("offset of age is [%d]\n", offsetof(struct stu, age));        printf("offset of score is [%d]\n", offsetof(struct stu, score));        printf("%d\n", (size_t)((int)&xiaoyuan.age - (int)&xiaoyuan));        printf("%d\n", (size_t)&(((struct stu*)0)->age) );   /* 相当于        * printf("%d\n", (size_t)(&(((struct stu*)0)->age)- 0) );        */        return 0;}


运行结果:

[root@localhost~]# ./a.outoffset of age is[20]offset of scoreis [24]2020