linuxでcontainer_of実装分析
カーネルバージョン:linux-2.6.37.1
container_ofのマクロ定義は次のとおりです.
container_の使用ofマクロの後、親構造体typeのメンバーメンバーメンバーの既知のアドレスptrによって探すことができる
現在のptrアドレスが属する親構造体typeのアドレス.
例:
struct teset *t = container_of(pt, struct test, tmp)
container_の使用ofマクロの後、既知のstruct tmpアドレスptによってpのアドレスを計算することができる.次の結合
例に基づいてcontainer_を分析するofマクロコード
アドレス(struct testアドレス)
さらにmptrを強制的にmemberタイプに変換し、最後にmptrに既知のアドレスptrを付与する.
これにより、最後にptrポインタからオフセット量を減算するだけで親構造体重typeが得られる
で行ないます.
例をまとめると、例えば、既知の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
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