linux内核中的container_of宏
来源:互联网 发布:仙界网络直播间txt 编辑:程序博客网 时间:2024/05/25 12:21
//xk> 引子
首先看一个简单的面试题:定义一个宏FIND(stru, e),求结构体stru中某个成员e相对于stru的偏移量。
题目的解答很简单:
#define FIND(stru, e) &(((stru *)0)->e)
将常量0强制类型转化为stru *类型的指针。因为结构体的首地址为0,所以其成员的地址即为相对于结构体的偏移量。
顺便提一点,C++中不能直接用&对一个类的成员函数取地址,实现这个目的的技巧参见《C++编程思想》。C++中可以直接用&对一个类的数据成员取地址,因为数据成员和成员函数存放在不同的内存区。
//xk> 正文
Linux中广泛运用容器机制。如果struct A中嵌入包含一个子结构B,则称A是B的一个容器。
比如作为Linux标准数据结构的循环双链表,是由一个一个的表头连接起来的,而这些表头就嵌入在双链表所管理的各种类型的对象之中。注意这里的表头不是指链表的表头,而是链表的元素,是被管理对象在链表中的引子,很多时候我们称被管理对象为链表元素。这样做有两个好处:1. 被管理的对象可能类型迥异,而表头的结构统一而简单。2. 双链表应用非常广泛,因为表头结构统一,内核可以提供一套标准的循环双链表操作。
通过循环双链表很容易找到链表上的某个表头,我们关注的是怎样通过嵌入在容器中的表头,找到被管理的那个对象的首地址。
以循环双链表为例,list_entry宏提供了这个功能
// list.h#define list_entry(ptr, type, member) container_of(ptr, type, member)而container_of宏则是内核真正用来实现该目的的宏:根据嵌入的子结构成员返回容器首地址。
根据成员返回结构首地址,简言之:成员的地址 - 成员相对于结构首地址的便宜量 = 结构首地址。linux内核提供offsetof宏来做这个事情
// kernel.h#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) // 访问结构指针成员操作符-> 的优先级高于 取地址操作符&注意操作符优先级:访问结构指针成员操作符-> 高于 取地址操作符& 高于 强制类型转换操作符()
到这里都很简单,不过下一步形式有点复杂:
// kernel.h/** * container_of 从结构的成员来获得容器实例 * @ptr: 指向成员数据的指针 * @type: 容器结构的类型 * @member: 成员在容器内的名称 */#define container_of(ptr, type, member) \({ \ const typeof( ((type *)0)->member) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type, member) ); \})其核心依然很简单,两步走:
(1) 创建一个指针__mptr,其值等于ptr。其类型为member的类型。(《深入linux内核架构》说其类型为type,还举了个例子,应该是错的,指针不能隐式类型转换,所以__mptr与ptr类型相同才能赋值)
(2) __mptr - 偏移量即得到首地址。强制类型转换(char *)是为了保证指针运算以字节为单位。通常指针运算表示指向数组的下一个元素,因此指针 + 1的结果与指针的类型相关。强制类型转换(type *)是因为这个宏的结果应该是容器结构的类型type,返回的是容器结构首地址嘛。
为啥不直接用ptr,而要生成一个const的__mptr呢?难道container_of宏可能修改ptr?
- linux内核中的container_of宏
- Linux内核中的container_of宏
- Linux内核中的container_of()
- linux内核中的container_of
- Linux内核中的常用宏--container_of(container_of(ptr, type, member)
- Linux内核container_of宏
- Linux内核,container_of 宏
- Linux内核中的container_of浅析
- Linux内核中的常用宏container_of其实很简单
- Linux内核中的常用宏container_of其实很简单
- Linux内核中的常用宏container_of其实很简单
- Linux内核中的常用宏container_of其实很简单
- Linux内核中的常用宏container_of其实很简单
- Linux内核中的常用宏container_of其实很简单
- Linux内核中的常用宏container_of其实很简单
- Linux内核中的常用宏container_of其实很简单
- Linux内核中的常用宏container_of其实很简单
- Linux内核中的常用宏container_of其实很简单
- FPGA无法下载
- Java 正则表达式基础
- 这本书,从中间读
- 比较字符串和数字串
- 建立ssh远程控制
- linux内核中的container_of宏
- 比较所有的字段类型
- ios Bundle的使用
- 有关日期的SAP函数使用
- MATLAB图像处理相关函数 非常有用
- 比较字符串和数字串(续)
- cygwin中访问windows分区
- textField被虚拟键盘挡住的3种解决方法
- 使用.NET操作SQLLITE