container_of宏定义解析

container_of宏,定义kernel.h中:

/**
* container_of - cast a member of a structure out to the containing structure
* @ptr:     the pointer to the member.
* @type:     the type of the container struct this is embedded in.
* @member:     the name of the member within the struct.
*
*/
#define container_of(ptr, type, member) ({             /
         const typeof( ((type *)0)->member ) *__mptr = (ptr);     /
         (type *)( (char *)__mptr - offsetof(type,member) );})

container_of在Linux Kernel中的应用非常广泛, 它用于从结构体成员获取结构体的地址。定义中:

typeof:这是gcc的C语言扩展保留字, 用于从变量获取类型

offsetof在stddef.h中, 用来获得一个结构体成员的相对偏移量

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

offsetof 是怎么做到的呢?它把0地址强制转化成了TYPE*类型,然后将它的MEMBER成员的地址转化为size_t类型。也就是说如果一个类型为TYPE的结 构体地址从0开始,那么它的MEMBER成员的地址就是MEMBER成员与TYPE类型地址之间的相对偏移量(以char计数的)。

好了,让我们开始解析container_of:

这个宏传入3个参数:ptr(type的成员的地址),type(结构体类型),member(成员的名称)

第一行:const typeof( ((type *)0)->member ) *__mptr = (ptr);

首 先要正确的取得member地址,因为参数中没有传入member的类型,所以要通过typeof( ((type *)0)->member ) *搞出member的类型,typeof括号中的式子与offsetof中的作用类似,取得了member之后再使用typeof得到它的类型。所以第一 行的结果就是__mptr是member类型的指向ptr地址的常量指针。

第二行:(type *)( (char *)__mptr - offsetof(type,member) );

取得了member的地址之后,只要把它减去member相对于结构体的偏移量,就可以得到结构体的地址了。最后,再把这个地址转化成type*,就完成了整个逻辑。

时间: 2024-10-25 17:03:39

container_of宏定义解析的相关文章

linux内核头文件kdev_t.h 宏定义解析

kdev_t.h 宏定义解析 这个header file反正不多,直接原因是--遇到了,就搞定它! dev_t 类型的变量定义在linux/types.h 用来保存设备编号--包括主设备号和次设备号.dev_t 是一个32位的数,其中12位用来表示设备号,其余20位用来表示次设备号. 始终不要对这32位是高12位是主设备号还是低2位是主设备号做出假定,不利于代码的可移植性,始终记得使用宏定义来处理dev_t ! 都在这里了: #define MINORBITS 20 //次设备号的占位数目 #d

linux中offsetof与container_of宏定义

linux内核中offsetof与container_of的宏定义 #define offsetof(TYPE, MEMBER)    ((size_t) &((TYPE *)0)->MEMBER) /** * container_of - cast a member of a structure out to the containing structure * @ptr:        the pointer to the member. * @type:       the type

Linux 内核中 likely 与 unlikely 的宏定义解析

在 2.6 内核中,随处可以见到 likely() 和 unlikely() 的身影,那么为什么要用它们?它们之间有什么区别? 首先要明确: if(likely(value)) 等价于 if(value) if(unlikely(value)) 也等价于 if(value) 也就是说 likely() 和 unlikely() 从阅读和理解代码的角度来看,是一样的!!! #define likely(x) __builtin_expect((x),1) #define unlikely(x) _

Linux下的两个经典宏定义 转

http://www.linuxidc.com/Linux/2016-08/134481.htm http://blog.csdn.net/npy_lp/article/details/7010752 http://www.linuxdiyf.com/viewarticle.php?id=104768 本文首先介绍Linux下的经典宏定义,感受极客的智慧,然后根据该经典定义为下篇文章作铺垫. offsetof宏定义: // 获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量.#

C语言之offset_of宏和container_of宏

通过结构体整体变量来访问其中各个元素,本质上是通过指针方式来访问的,形式上是通过.的方式来访问的(这时候其实是编译器帮我们自动计算了偏移量). 1:offset_of宏 作用:计算结构体中某个元素和结构体首地址的偏移量(其实质是通过编译器来帮我们计算). 定义: #define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER) 参数分析:TYPE是结构体类型,MEMBER是结构体中一个元素的元素名 返回值:member元素相对于整个结构体

Linux下的两个经典宏定义【转】

转自:http://www.linuxidc.com/Linux/2015-07/120014.htm 本文首先介绍Linux下的经典宏定义,感受极客的智慧,然后根据该经典定义为下篇文章作铺垫. offsetof宏定义: // 获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量.#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 说明:获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移

Linux下的两个经典宏定义

本文首先介绍Linux下的经典宏定义,感受极客的智慧,然后根据该经典定义为下篇博客作铺垫. offsetof宏 定义: // 获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 说明:获得结构体(TYPE)的变量成员(MEMBER)在此结构体中的偏移量. 1.( (TYPE *)0 ) 将零转型为TYPE类型指针,即TYPE类型的指针的地址是0.

深入浅出实例解析linux内核container_of宏

做一件事情首先应该知道它的目的是什么. container_of的目的:如何通过结构中的某个变量获取结构本身的指针. 总体思路:假想一下,你的结构体中有好几个成员,你如何通过里面的"任一成员"获取整个结构体的首地址呢.container_of的做法就是通过typeof定义一个与"任一成员"同类型的指针变量pvar_a(假设变量名就是pvar_a),并让指针变量pvar_a指向这个"任一成员",然后用 "pvar_a的地址" 减

container_of宏剖析

container_of宏剖析//该宏位于include/linux/kernel.h 1.定义格式 /** * container_of - cast a member of a structure out to the containing structure * * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member:the nam