linux中container_of实现分析

内核版本:linux-2.6.37.1

container_of的宏定义如下:

#define container_of(ptr, type, member) ({			\
	const typeof( ((type *)0)->member ) *__mptr = (ptr);	\
	(type *)( (char *)__mptr - offsetof(type,member) );})

使用container_of宏后,可通过父结构体type中的成员member的已知地址ptr,来寻找

当前ptr地址所属的父结构体type的地址。

例子:

struct test{
    int     a,
    char  b,
    struct   tmp,
}

struct tmp *pt
pt = &p.tmp (p是从其他途径获得的结构体,现在需要计算这个p的地址) 

struct teset *t = container_of(pt, struct test, tmp)

使用container_of宏后可以通过已知的struct tmp地址pt来计算得到p的地址。下面结合

根据例子分析container_of宏代码

const typeof( ((type *)0)->member ) *__mptr = (ptr);
将mptr指针将之转换成member类型的指针。这是通过首先将0地址强制转换成type类型的

地址(即struct test地址)

struct test{                      0x00000000
    int     a,                    0x00000000
    char  b,                      0x00000004
    struct   tmp,                 0x00000005
}
然后通过typeof(X->member)来获得type类型中member的类型,

再将mptr强制转换为member类型,最后对mptr赋已知的地址ptr。

这样最后只要通过ptr指针减去一个偏移量即可获得父结构体重type

的地址。

(type *)( (char *)__mptr - offsetof(type,member) );})

结合例子总结:例如已知p.tmp的地址pt为0x30005646,通过offsetof(type,member)可以算的

tmp在test中的偏移量为5,则计算可得父结构体p的地址为子结构体tmp的地址0x300005646减

去tmp在父结构体中的偏移量5,即0x30005646-5 = 0x30005641

你可能感兴趣的:(linux,struct)