linux内核之container_of()详解(即:list_entry()的详解)
来源:互联网 发布:主力资金净流入额 知乎 编辑:程序博客网 时间:2024/06/06 09:32
在linux内核链表中,有两个点我认为设计的比较巧妙。
第一个是链表项中没有数据项,而是在要使用链表时,定义个数据项结构体,然后把链表项结构体定义为数据项结构体的成员(这个将在下一篇博文中详细阐述)。如果要对数据项结构体中数据进行访问,则通过本文要分析的函数(或者说宏)来解决。
第二个是container_of(ptr, type, member)这个宏,这个宏的作用是已知一个结果体的类型type,和一个结构体的成员变量member,(ptr = &member)。就可以求的出结构体的首地址。其实这是解决上一个设计巧妙的地方所带来的问题。
先来看下这个宏的用处:
假设:有个结构体typedef struct test{......}T;其结构体成员都知道的(假设里面有个成员变量为member,他所在的结构体中的位置随意)。现在已知某个(未知结构体变量名)结构体变量中的成员变量member,求该结构体变量中的其他成员变量。
分析:求其他结构体变量中的成员,其实只要求出member所在的结构体变量的首地址即可,通过首地址指针一个个遍历。
答案:用container_of()宏来求解。这个宏就是用来求 已知某个结构体变量中的某个成员所在的结构体变量首地址。member所在的结构体变量首地址 = container_of(&member,T,member);
接下来分析下container_of()宏的实现:
#define list_entry(ptr, type, member) /
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
先来逐个分析下:
减号右边分析:(unsigned long)(&((type*)0)->member) (type*)0: 把0地址强制转换成type结构体的地址,表示0地址处存放了type类型的结构体变量,为什么在0处强转为结构体地址,这也是个设计巧妙点;((type*)0)->member:这个表示指向结构体变量中的成员member;&(((type*)0)->member)):这个当然是结构体变量中member的地址了,但是这里转了下弯,这是不仅表示是结构体变量中成员member的地址,还表示了结构体变量中的member成员到结构体变量的首地址的距离,也就是说member相对于首地址的偏移量。偏移量本应该是这么算的:member的地址 - 首地址。但首地址强转在0处,所以member的地址就是偏移量。(unsigned long)是把偏移量强转为整型。
减号左边的就很好分析了。用实际的member地址减去偏移量,就得到了变量的首地址了。然后再强转为结构体类型。(char*)是因为前面的偏移量是用unsigned long来表示的。大概原理就是这样的了。其实很简单,关键点是在0处强转为结构体类型,以至于得到member的地址就是偏移量。
请看下面原理图:
有关于container_of()的实例小程序请看:http://blog.csdn.net/yuzhihui_no1/article/details/38407443
- linux内核之container_of()详解(即:list_entry()的详解)
- Linux内核container_of详解(图解)
- Linux内核container_of详解(图解)
- Linux内核container_of详解(图解)
- Linux内核container_of详解(图解)
- linux内核container_of详解
- Linux内核container_of详解
- linux内核链表之list_entry(ptr,type,member)函数详解
- 内核链表list_entry()宏详解
- 内核链表中list_entry()函数 以及typeof的用法详解
- Linux内核中list_head、list_for_each、list_entry、container_of之间的关系
- list_entry()宏详解
- linux内核中container_of详解
- linux内核中container_of详解
- linux内核之container_of()应用
- Linux内核源码中container_of详解
- Linux内核中container_of函数详解
- 详解Linux内核之双向循环链表(2) list_for_each/list_entry/list_for_each_entry
- Babelfish
- HDU 2571 命运
- AutoCompleteTextView
- 【C#】DataGridView中指定的单元格不能编辑
- 加入epoll_wait之后的简化版本
- linux内核之container_of()详解(即:list_entry()的详解)
- CDOJ-#851 方老师与素数(BFS)
- priority_queue用法(转载)
- JUnit4
- JavaScript基础学习
- OC 构造函数
- MemSQL Start[c]UP 2.0 - Round 1 C. Magic Trick
- 网站空间【收藏】
- Android 图片缓存机制