很美的container_of

1341阅读 0评论2012-10-31 时间看来
分类:嵌入式

在LDD的第3章字符设备驱动中看到container_of这个函数,那个时候很不好理解。后面11章内核中的数据类型,14章Linux设备模型中又接触到这个函数。

内核中的数据类型,链表一节中讲了链表相关的接口,其中有个有趣的函数list_entry(ptr, type, member),/linux/list.h中有

点击(此处)折叠或打开

  1. #define list_entry(ptr, type, member) \
  2.     container_of(ptr, type, member)

点击(此处)折叠或打开


点击(此处)折叠或打开

  1. struct list_head { struct list_head *next, *prev; };

  2.     struct todo_struct
  3.     {
  4.     struct list_head list;
  5.     int priority; /* driver specific */
  6.     /* ... add other driver-specific fields */
  7.     };

  8. void todo_add_entry(struct todo_struct *new)
  9. {
  10. struct list_head *ptr;
  11. struct todo_struct *entry;
  12. for (ptr = todo_list.next; ptr != &todo_list; ptr = ptr->next)
  13. {
  14.     entry = list_entry(ptr, struct todo_struct, list);
  15.     if (entry->priority < new->priority) {
  16.     list_add_tail(&new->list, ptr);
  17.     return;
  18.     }
  19. }
  20. list_add_tail(&new->list, &todo_struct)
  21. }




在/linux/kernel.h中对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) );})

对于一些底层结构体,比如list_head, kobject, kobj_type, kset, subsyetem ,他们被上层结构体包含的时候,就可以用container_of返回一个指向上层容器的指针。




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

宏功能:获得一个结构体变量成员在此结构体中的偏移量。

1. ( (TYPE *)0 ) 将零转型为TYPE类型指针;
2. ((TYPE *)0)->MEMBER 访问结构中的数据成员;
3. &( ( (TYPE *)0 )->MEMBER )取出数据成员的地址,即相对于0的偏移量,要的就这个;
4.(size_t)(&(((TYPE*)0)->MEMBER))结果转换类型,size_t应该最终为unsigned int类型。
此宏的巧妙之处在于将 0 转换成(TYPE*),这样结构体中成员的地址即为在此结构体中的偏移量。

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

宏功能:从结构体(type)某成员变量(member)指针(ptr)来求出该结构体(type)的首指针。

1、.typeof( ( (type *)0)->member )为取出member成员的变量类型。

2、定义__mptr指针ptr为指向该成员变量的指针

3、mptr为member数据类型的常量指针,其指向ptr所指向的变量处

4、.(char *)__mptr转换为字节型指针。(char *)__mptr - offsetof(type,member))用来求出结构体起始地址(为char *型指针),然后(type *)( (char *)__mptr -offsetof(type,member) )在(type *)作用下进行将字节型的结构体起始指针转换为type *型的结构体起始指针。
5、.({ })这个扩展返回程序块中最后一个表达式的值。





上一篇:四则运算(未解决)
下一篇:文件 数据库 数据库管理系统