linux内核常用宏
container_of
定义如下:
/* linux-2.6.38.8/include/linux/kernel.h *
* 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) );})
作用是通过结构体内成员的地址来得到结构体的首地址。
其中offsetof宏定义如下:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
其作用是用来得到结构体内成员相对于结构体首地址的偏移量。
理解:
offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
两个宏都非常巧妙的运用的0地址,offsetof中 &((TYPE *)0)->MEMBER) 可以看成把0地址强制类型转换为TYPE*类型,然后指向MEMBER成员,&得到MEMBER成员的地址,由于TYPE地址为0,所以得到的就是MEMBER成员相对于结构体首地址的偏移量,最后用(size_t)强制类型转换为整数。
size_t 就是size type,一般用来表示一种计数,比如有多少东西被拷贝等。例如:sizeof操作符的结果类型是size_t,该类型保证能容纳实现所建立的最大对象的字节大小。 它的意义大致是“适于计量内存中可容纳的数据项目个数的无符号整数类型”。所以,它在数组下标和内存管理函数之类的地方广泛使用。使用size_t是为了在增强程序的可移植性。
container_of
有了对offsetof的理解,对container_of的理解就不难了。
第一句 const typeof( ((type *)0)->member ) *__mptr = (ptr); 使用typeof推导出 ( ((type *)0)->member ) * 得到结构体内成员的变量类型指针 ,定义为变量__mptr,地址为(ptr)。之后( (char *)__mptr - offsetof(type,member) ) 将__mptr强制类型转换为 char* 类型,目的是为了相减时能够以一字节为单位相减,C语言中指针的加减操作是以指针类型的大小为单位进行操作的。最后类型转换为(type *)得到结构体首地址。