Linux内核之container_of详细解析

container_of用来根据成员变量查找所在基结构体的地址,其宏定义如下:
#define container_of(ptr, type, member) ({                      \
        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
        (type *)( (char *)__mptr - offsetof(type,member) );})

ptr    : 成员变量的地址
type   : 要查找基结构体的变量类型
member : 成员变量名字        

现在来分析下这是个什么玩意:
1. 先定义一个结构体       
struct Person
{
    char* name;
    unsigned int  age;
    unsigned int  tall;
};     
  

2. 用Person结构体定义一个变量:
    struct Person Man;

下面我们通过成员变量tall来查找结构体Man的地址:  
3. 用变量去替代宏container_of:
#define container_of(&Man.tall, struct Person, tall) ({                      \
        const typeof( ((struct Person *)0)->tall ) *__mptr = (&Man.tall);    \
        (struct Person *)( (char *)__mptr - offsetof(struct Person,tall) );})


4. 先来分析: const typeof( ((struct Person *)0)->tall ) *__mptr = (&Man.tall);
    1) (struct Person *)0) : 将0地址开始的地方,转化为结构体类型指针(struct Person *)
    2) (struct Person *)0)->tall : 取指针的成员tall
    3) typeof( ((struct Person *)0)->tall ) : 获取成员的数据类型(如,int,char, double)
    4) 到此为止,可看成 const int *__mptr = (&Man.tall);  //int是我们第三步获取的,这一步建立一个临时指针__mptr,这个指针将在后面用到




5 再来分析: (struct Person *)( (char *)__mptr - offsetof(struct Person,tall) );
    1)  offsetof(struct Person,tall) : 这又是个宏,定义如下:
        #define offsetof(TYPE,MEMBER) ((size_t)&((TYPE *)0)->MEMBER)
            替换掉-->  #define offsetof(struct Person,tall) ((size_t)&((struct Person *)0)->tall)
                      --> ((size_t)&((struct Person *)0)->tall) : 拿到地址的数值,注意,地址是从0开始的,这里拿到的其实是成员在结构体中的偏移量
        
    2) (struct Person *)( (char *)__mptr - 偏移量 ): 成员地址减去偏移量,就是结构体地址了。
    

你可能感兴趣的:(linux,Linux内核)