linuxでcontainer_of実装分析

1574 ワード

カーネルバージョン: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のメンバーメンバーメンバーの既知のアドレス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が0 x 3005646であり、offsetof(type,member)によって算出できる
tmpのtestにおけるオフセット量が5であると、計算可能な親構造体pのアドレスがサブ構造体tmpのアドレス0 x 30005646から減少する
親構造体における脱tmpのオフセット量5、すなわち0 x 30005646-5=0 x 30005641