宏定义位于:include/linux/kernel.h
#define container_of(ptr, type, member) ({ /
const typeof( ((type *)0)->member ) *__mptr = (ptr); /
(type *)( (char *)__mptr - offsetof(type,member) );})
这个宏用于从包含在某个结构中的指针获得结构本身的指针,通俗的讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址,很浅显易懂了吧。
下面简单分析下这个宏定义
其中需要说明的是offsetof,它定义在include/linux/stddef.h中
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
1. ( (TYPE *)0 ) 将0转型为TYPE类型指针;
2. ((TYPE *)0)->MEMBER 访问结构中的数据成员MEMBER ;
3. &( ( (TYPE *)0 )->MEMBER )获取数据成员的地址;
4. 将地址转换类型,获得偏移值,由于结构体是从0开始的,那么member的地址即为member相对于该结构体首地址的偏移
综上,offset宏作用为获取TYPE结构体中MEMBER成员的偏移
下面我们对contains_off进行整体分析
#define container_of(ptr, type, member) ({ /
const typeof( ((type *)0)->member ) *__mptr = (ptr); /
(type *)( (char *)__mptr - offsetof(type,member) );}
1、 const typeof( ((type *)0)->member ) *__mptr = (ptr);
//获得type结构体member成员的类型,定义暂存指针__mptr,将member赋值给__mptr
2、(type *)( (char *)__mptr - offsetof(type,member) );
//将member地址__mptr减去利用offset得到的member成员的偏移,即为结构体的开始地址。
使用示例
#include<stdio.h>
typedef struct
{
int i;
char c;
float f;
}test_struct;
void main(void)
{
test_struct *struct_ptr = NULL;
test_struct init_s ={1, 'a', 1.1};
char *ptr_c = &init_s.c; //已知了test_struct中成员c地址
struct_ptrt = container_of(ptr_c, test_struct, c); //利用宏获取init_s地址
printf("struct_ptr =%#x\n", struct_ptr);
}