揭開linux內核中container_of的神祕面紗linux
做者:程姚根,華清遠見嵌入式學院講師。web
在linux 內核中有一個大名鼎鼎的宏container_of(),這個宏是用來幹嗎的呢?咱們先來看看它在內核中是怎樣定義的。spa
呵呵,乍一看不知道是什麼東東。指針
咱們先來分析一下container_of(ptr,type,member),這裏面有ptr,type,member分別表明指針、類型、成員。看一個例子:orm
Struct test
{
int i;
int j;
char k;
};
Struct test temp;ci
如今呢若是我想經過temp.j的地址找到temp的首地址就能夠使用container_of(&temp.j,struct test,j);get
如今咱們知道container_of()的做用就是經過一個結構變量中一個成員的地址找到這個結構體變量的首地址。it
下面來看看比較複雜的內容:form
咱們用上面的struct test張展一下test
Const typeof(((struct test *)0)->j) * __mptr = (&temp.j);
其中,typeof是GNU C對標準C的擴展,它的做用是根據變量獲取變量的類型。所以,上述代碼的做用是首先使用typeof獲取結構體成員j的類型爲int,而後頂一個int指針類型的臨時變量__mptr,並將結構體變量中的成員的地址賦給臨時變量__mptr。
(struct test *)((char *)__mptr - offsetof(struct test,j));
接着咱們來看一下offsetof(struct test,j),他在內核中以下定義
展開(size_t)&((struct test *)0)->j,這是什麼東東?
一開始也不明白,這裏要感謝曹老師老師的熱心幫助,一語驚醒夢中人,呵呵,能夠是這樣理解。
其中size_t是整型,那麼咱們能夠知道最終的結果是一個整形值,也就是j相對於0地址的偏移量。也許如今你會問,整出這麼個玩意幹嗎,下面看個列子:
程序運行結果:
發現沒有若是把第二個值 減去最後一個值,就能獲得第一個值。
在回首一下它:
(struct test *)((char *)__mptr - offsetof(struct test,j));
是否是能夠得到結構體變量temp的首地址呀,是否是太精妙了呀,linux內核中隨隨便便一個宏就有如此精妙,呵呵,想一想對linux瞭解很是多的牛人,還有很長一段路。