linux上container_of宏使用

1.简介

  在Linux上container_of宏使用较为常见,该宏的作用是通过知道结构体中一个成员的地址,从而
计算出,整个结构体的地址,在linux上很多结构体中都包含有struct list_head结构体,通过该list,就可以
得到整个结构体的地址,从而进行操作。

2.解释

  在知道container_of之前,首先需要先知道一个offsetof(TYPE, MEMBER)

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

上述结构是计算出MEMBER在结构体中的偏移量
测试参考:

  在知道offsetof宏后,container_of的构成

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

  上述为linux4.14上实现,通过member的指针地址-偏移的地址量=计算整个结构体的地址,注意好类型转换,
也就是指针步长(这里转换为char *)。   当然在linux5.0后,该宏进一步演化(增加了)类型判断检查

#define container_of(ptr, type, member) ({              \
    void *__mptr = (void *)(ptr);                   \
    BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
             !__same_type(*(ptr), void),            \
             "pointer type mismatch in container_of()");    \
    ((type *)(__mptr - offsetof(type, member))); })

其中BUILD_BUG_ON_MSG,这个在编译的时候,就会对指针类型进行判断。