神奇的container_of

来源:互联网 发布:c语言调用golang 编辑:程序博客网 时间:2024/06/10 07:03
container_of是linux内核中常用的一个宏,这个宏的功能是,根据某个结构体字段的指针,找到对应的结构体指针。

话不多说,先上源码:

/*** 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) );})

第一个参数为指向结构体中的成员的指针,第二个参数为结构体类型,第三个参数为结构体成员的名字。

 
如图,一个结构体struct a中包含三个成员b,c,d,一个指向成员c的指针p_c,通过container_of(p_c, struct a, c)就可以计算出指向c所在的结构体的指针p_a


原理说明:
这个宏的原理是结构体成员指针ptr,减去结构体成员与此结构体首地址的偏移量(这个偏移量由offsetof宏获得),就得出了结构体首地址。这个功能是由宏声明的第三行实现的。
那么宏声明的那二行是干什么用的呢?它仅仅是把ptr重新赋值给了__mptr,看似没用。实际上这里起到了给开发者提醒的功能。如果开发者传入的ptr指针指向的类型,与结构体中成员的类型不符,编译器在这里会打印一条warning,提示开发者可能存在的错误。


测试代码:
#include <stdio.h>#include <linux/kernel.h>#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)#define container_of(ptr, type, member) ({                      \        const typeof ( ((type *)0)->member ) *__mptr = (ptr);    \        (type *)( ( char *)__mptr - offsetof(type,member) );})struct a {                 int b ;                 int c ;                 int d ;};int main( int argc, char *argv[]){                 struct a a_obj, *p_a;                 int *p_c;                p_c = &a_obj. c ;                p_a = container_of(p_c, struct a, c);                 printf ("a_obj addr:%x\na_obj addr obtained by container_of: %x\n", ( unsigned int )&a_obj, ( unsigned int )p_a);                 return 0;}
打印结果:
a_obj addr:bfffed98
a_obj addr obtained by container_of: bfffed98



原创粉丝点击