Loading... `container_of`宏是Linux内核编程中的一个常用工具,用于从结构体中的成员指针计算出该结构体的指针。它在数据结构和内存管理中非常有用,尤其在处理嵌入式系统和内核模块开发时。 ### 一、`container_of`宏的定义 `container_of`宏的定义在Linux内核的 `include/linux/kernel.h`头文件中,其实现如下: ```c #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) *__mptr = (ptr); \ (type *)((char *)__mptr - offsetof(type, member)); }) ``` #### 1.1 参数解析 - `ptr`:指向结构体成员的指针。 - `type`:包含该成员的结构体类型。 - `member`:结构体中的成员名称。 ![](https://www.8kiz.cn/usr/uploads/2024/06/594011763.png) ### 二、`container_of`的工作原理 `container_of`通过计算成员在结构体中的偏移量,再减去这个偏移量,从而得到结构体的起始地址。核心在于 `offsetof`宏,该宏计算成员相对于结构体起始位置的偏移量。 ```c #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) ``` `offsetof`宏通过将0类型转换为目标结构体类型,然后取成员的地址,再将其转换为size_t类型,就得到了成员的偏移量。 ### 三、使用 `container_of`宏的实例 假设有如下结构体定义: ```c struct example { int a; double b; char c; }; ``` 我们希望通过结构体成员 `b`的指针找到结构体 `example`的起始地址。 #### 3.1 实例代码 ```c #include <stdio.h> #include <stddef.h> // 包含offsetof宏定义 struct example { int a; double b; char c; }; int main() { struct example ex; struct example *pex; double *pb = &ex.b; pex = container_of(pb, struct example, b); printf("Address of ex: %p\n", (void *)&ex); printf("Address of pex: %p\n", (void *)pex); return 0; } ``` 在这个例子中,`container_of`宏用于从指向成员 `b`的指针 `pb`获取到包含它的结构体 `example`的指针 `pex`。 #### 3.2 运行结果 运行上述代码,输出结果应为: ``` Address of ex: 0x7ffee4b5d740 Address of pex: 0x7ffee4b5d740 ``` 这表明通过 `container_of`宏,我们成功地从结构体成员指针找回了结构体指针。 ### 四、`container_of`宏的实际应用 `container_of`宏在Linux内核中有广泛的应用,尤其在处理通用数据结构(如链表、树等)时。例如,内核中的链表结构定义如下: ```c struct list_head { struct list_head *next, *prev; }; ``` 假设有一个包含链表节点的结构体: ```c struct my_struct { int data; struct list_head list; }; ``` 要从链表节点指针获取包含它的结构体指针,可以使用 `container_of`宏: ```c struct list_head *node; struct my_struct *entry; entry = container_of(node, struct my_struct, list); ``` ### 五、注意事项 1. **类型安全**:确保 `ptr`参数指向的确实是 `type`结构体中的 `member`成员,否则会导致未定义行为。 2. **指针有效性**:`ptr`参数必须是有效的指针,不能是空指针或野指针,否则会导致运行时错误。 3. **宏扩展**:`container_of`是一个宏,它在编译时展开,需要注意其在不同编译环境中的行为。 ### 六、总结 `container_of`宏是Linux内核编程中处理复杂数据结构的利器,通过它可以轻松地从结构体成员指针获取到整个结构体指针。理解并熟练使用 `container_of`宏对于编写高效、简洁的内核代码至关重要。 ### 思维导图 ```plaintext 使用container_of宏进行类型转换 ├── 一、定义 │ ├── container_of宏的定义 │ └── 参数解析 ├── 二、工作原理 │ ├── 通过offsetof计算偏移量 │ └── 计算结构体起始地址 ├── 三、实例 │ ├── 结构体定义 │ ├── 示例代码 │ └── 运行结果 ├── 四、实际应用 │ ├── 链表示例 │ └── 从链表节点获取结构体 ├── 五、注意事项 │ ├── 类型安全 │ ├── 指针有效性 │ └── 宏扩展 └── 六、总结 ``` 通过以上内容,读者应能清晰地理解 `container_of`宏的用途和用法,能够在实际编程中有效地应用该宏进行类型转换。 最后修改:2024 年 07 月 02 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏