天天看點

container_of宏

在linux 核心中有一個大名鼎鼎的宏container_of(),這個宏是用來幹嘛的呢?我們先來看看它在核心中是怎樣定義的。

container_of宏

呵呵,乍一看不知道是什麼東東。

我們先來分析一下container_of(ptr,type,member),這裡面有ptr,type,member分别代表指針、類型、成員。看一個例子:

Struct test
{
    int i;
    int j;
    char k;
};
Struct test temp;      

現在呢如果我想通過temp.j的位址找到temp的首位址就可以使用container_of(&temp.j,struct test,j);

現在我們知道container_of()的作用就是通過一個結構變量中一個成員的位址找到這個結構體變量的首位址。

下面來看看比較複雜的内容:

container_of宏

我們用上面的struct 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),他在核心中如下定義

container_of宏

展開(size_t)&((struct test *)0)->j,這是什麼東東?

一開始也不明白,這裡要感謝曹忠明老師的熱心幫助,一語驚醒夢中人,呵呵,可以是這樣了解。

container_of宏

其中size_t是整型,那麼我們可以知道最終的結果是一個整形值,也就是j相對于0位址的偏移量。也許現在你會問,整出這麼個玩意幹嘛,下面看個列子:

container_of宏

程式運作結果:

container_of宏

發現沒有如果把第二個值 減去最後一個值,就能得到第一個值。

在回首一下它:

(struct test *)((char *)__mptr - offsetof(struct test,j));      

要注意的是代碼高亮處 ,(char *)__mptr 的作用是将__mptr強制轉換為字元指針類型,必須的!! 如果_mptr為整形指針 __mptr - offset 相當于減去 sizeof(int)*offset個位元組!!!