container_of()宏

  最近学习为Android添加编写内核驱动,遇到的第一个问题就是linux中大名鼎鼎的container_of()宏。

  container_of()是Linux内核中一个非常重要的宏,主要功能就是:根据结构体中一个域成员的地址获取整个结构体的地址。

  container_of()定义如下:

 1 /**
 2  * container_of - cast a member of a structure out to the containing structure
 3  * @ptr:    the pointer to the member.
 4  * @type:    the type of the container struct this is embedded in.
 5  * @member:    the name of the member within the struct.
 6  *
 7  */
 8 #define container_of(ptr, type, member) ({            \
 9     const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
10     (type *)( (char *)__mptr - offsetof(type,member) );})

  路径:(Android源码)//kernel/goldfish/include/linux/kernel.h(学习android,就使用Android中的kernel代码了)。

  该宏的执行主要分为两步:

  第一步、定义一个变量保存传入的域成员的地址。

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

  以0为内存地址并强转为type类型(传入的结构体),通过->member(传入的域成员)获取到结构体的域成员,并用typeof()取得域成员的类型,以域成员的类型定义一个临时变量__mptr,把域成员的地址ptr保存到__mptr中。

  第二步、使用域成员地址减去域成员相对于结构体首地址的偏移。

  这一步首先使用offsetof()取得域成员相对于结构体首地址的偏移,再使用域成员的实际地址__mptr减去该偏移就可以得到结构体的首地址。

  下面以一张图来形象的描述该过程:

  

  当前传入域成员k的地址0x0010008,需要获取整个结构体的地址。首先使用offsetof()获取k相对于结构体地址的偏移8,再用0x0010008-8=0x00010000,这就是结构体的地址。

  理解清楚了就会发现是很简单的一件事。

  参考:

  http://www.cnblogs.com/sdphome/archive/2011/09/14/2176624.html

  http://www.cnblogs.com/hicjiajia/archive/2012/07/01/2571791.html

  http://blog.csdn.net/npy_lp/article/details/7010752

posted on 2015-04-15 16:12  skywalker0011  阅读(174)  评论(0编辑  收藏  举报

导航