詳解Linux內(nèi)核中的container_of函數(shù)
前言
在linux 內(nèi)核中,container_of
函數(shù)使用非常廣,例如 linux內(nèi)核鏈表 list_head
、工作隊列work_struct
中。
在linux內(nèi)核中大名鼎鼎的宏container_of()
,其實它的語法很簡單,只是一些指針的靈活應(yīng)用,它分兩步:
第一步,首先定義一個臨時的數(shù)據(jù)類型(通過typeof( ((type *)0)->member
)獲得)與ptr
相同的指針變量__mptr
,然后用它來保存ptr
的值。
第二步,用(char *)__mptr
減去member
在結(jié)構(gòu)體中的偏移量,得到的值就是整個結(jié)構(gòu)體變量的首地址(整個宏的返回值就是這個首地址)。
那這個宏到底是用來干嘛的呢?我們先來看看它在內(nèi)核中是怎樣定義的。
呵呵,乍一看不知道是什么東東。
我們先來分析一下container_of(ptr,type,member)
,這里面有ptr
,type
,member
分別代表指針、類型、成員。
看一個例子:
Struct test { int i; int j; char k; }; Struct test temp;
現(xiàn)在呢如果我想通過temp.j的地址找到temp的首地址就可以使用container_of(&temp.j,struct test,j);
現(xiàn)在我們知道container_of()
的作用就是通過一個結(jié)構(gòu)變量中一個成員的地址找到這個結(jié)構(gòu)體變量的首地址。
下面來看看比較復(fù)雜的內(nèi)容:
我們用上面的struct test張展一下
Const typeof(((struct test *)0)->j) * __mptr = (&temp.j); //(sturct test *)0 表示數(shù)據(jù)段基址
其中,typeof
是GNU C對標準C的擴展,它的作用是根據(jù)變量獲取變量的類型。因此,上述代碼的作用是首先使用typeof
獲取結(jié)構(gòu)體成員j的類型為int
,然后頂一個int指針類型的臨時變量__mptr
,并將結(jié)構(gòu)體變量中的成員的地址賦給臨時變量__mptr
。
(struct test *)((char *)__mptr - offsetof(struct test,j));
接著我們來看一下offsetof(struct test,j)
,他在內(nèi)核中如下定義
展開(size_t)&((struct test *)0)->j
,這是什么東東?
一開始也不明白,這里要感謝曹忠明老師的熱心幫助,一語驚醒夢中人,呵呵,可以是這樣理解。
其中size_t
是整型,那么我們可以知道最終的結(jié)果是一個整形值,也就是j相對于0地址的偏移量。也許現(xiàn)在你會問,整出這么個玩意干嘛,下面看個列子:
程序運行結(jié)果:
發(fā)現(xiàn)沒有如果把第二個值 減去最后一個值,就能得到第一個值。
在回首一下它:
(struct test *)((char *)__mptr - offsetof(struct test,j));
是不是可以獲得結(jié)構(gòu)體變量temp的首地址呀,是不是太精妙了呀
總結(jié)
linux內(nèi)核中隨隨便便一個宏就有如此精妙,想想對linux了解非常多的牛人,還有很長一段路。好了,以上就是本文的全部內(nèi)容了,希望這篇文章的內(nèi)容對大家的工作和學(xué)習(xí)能有所幫助,如果有疑問可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
SYN Cookie在Linux內(nèi)核中的實現(xiàn)
SYN Cookie在Linux內(nèi)核中的實現(xiàn)...2006-10-10Linux目錄結(jié)構(gòu)以及目錄內(nèi)的主要內(nèi)容詳細解析
以下是對Linux下的目錄結(jié)構(gòu)以及目錄內(nèi)的主要內(nèi)容進行了詳細的解析介紹。需要的朋友可以過來參考下2013-08-08Linux系統(tǒng)下如何查看及修改文件讀寫權(quán)限
linux下查看文件權(quán)限的命令2008-05-05