详解container_of宏

/* 整理于2012.11.27 于广工大 */

container_of宏原型定义:见内核源代码的include/linux/kernel.h文件,


    #define container_of(ptr, type,member) ({          \

        const  typeof( ((type *)0)->member ) *__mptr = (ptr);    \

        (type *)((char *)__mptr - offsetof(type,member) );})

这个宏定义中用到了另外两个宏:typeof和 offsetof。

对 typeof的理解:
实际上, typeof并不是宏定义,它是GCC的关键字,是GCC特有的特性。如果只知道一个变量的名字要得到其类型,并不是宏定义能够完成的,这需要编译时的信息。所以,typeof操作是GCC内置的功能,在内核头文件和Glibc头文件中都是找不到typeof的宏定义的。

对 offsetof的理解:
offsetof
是一个真正的宏,它定义在内核源代码 include/linux/stddef.h文件中:

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

在这里,TYPE表示一个结构体的类型,MEMBER是结构体中的一个成员变量的名字。

offsetof宏的作用是计算成员变量 MEMBER相对于结构体起始位置的内存偏移量,以字节(Byte)为单位。

offsetof
宏的计算原理是,把整数0进行强制类型转换,转换为一个 TYPE 类型的指针;然后找到成员变量MEMBER;最后用取地址符&得到 MEMBER的地址。

因为结构体是从地址0处开始的,所以 MEMBER 的地址就是MEMBER相对于结构体起始位置的偏移量。

对 container_of的理解:
三个参数, ptr是成员变量的指针, type是指结构体的类型, member是成员变量的名字。

container_of的作用就是在已知某一个成员变量的名字、指针和结构体类型的情况下,计算结构体的指针,也就是计算结构体的起始地址。计算的方法其实很简单,就是用该成员变量的指针减去它相对于结构体起始位置的偏移量。

    #define container_of(ptr, type,member) ({          \

        const  typeof( ((type *)0)->member ) *__mptr = (ptr);    \

        (type *)((char *)__mptr - offsetof(type,member) );})

在这个定义中,typeof( ((type *)0)->member)就是获得 member的类型,然后定义了一个临时的常量指针__mptr,指向 member变量。

为了避免对 ptr及prt指向的内容造成破坏,这里不直接使用 ptr 而要多多加一个__mptr。 把__mptr转换成 char *类型,因为offsetof得到的偏移量是以字节为单位。两者相减得到结构体的起始位置,再强制转换成type类型。

你可能感兴趣的:(详解container_of宏)