淺談container_of

在Linux 內核中,container_of 函數使用非常廣,例如 Linux內核鏈表 list_head、工作隊列work_struct中,它的作用就是通過結構體內成員的地址來找到這個結構體的地址,現在我們就來看看它到底是個什麼鬼東西

首先看看內核中它是如何定義的
在這裏插入圖片描述
原來是個宏,然後看下這個宏裏邊又包含了幾處不太清楚的地方,我們來一一探究

1、typeof

typeof是GNU C對標準C的擴展,它的作用是根據變量獲取變量的類型。
例如
在這裏插入圖片描述
它的輸出結果就是
size a=4 size b=4 size c=8, size d=8

2、((type *)0)->member

大眼一看,這是個什麼鬼東西,把0地址強轉成一個結構體指針,然後訪問其成員? 這有什麼用呢? 說這麼多還不如寫個代碼自己試試,直接上圖了
在這裏插入圖片描述它的輸出結果就是
((struct test_s *)0)->a=0 ->b=4 ->c=8

這好像就是各個變量相對於結構體本身的偏低地址,對了。就是這個作用,把0地址強轉成結構體類型後,它的成員變量的相對地址就恰好等於其在結構體內的便宜地址。

3、offsetof

先來看看它在內核裏的定義
在這裏插入圖片描述
發現是不是很熟悉,就跟我們前邊的實驗一模一樣 有沒有豁然開朗的感覺
到這裏,這個container_of似乎不再這麼神祕,大家應該能比較容易想到它是怎麼實現的了。

比如:

struct test_s{
	char a;
	int b;
	float c;
	short d;
}test;

如果我們要通過c的地址來找到這個test的地址,那我們只需要找到c成員相對於test的偏移地址即可。
即&test = &(test.c) - offset;
是不是覺得so easy?

好了,主要的部分就已經講完了,有沒有人好奇const typeof( ((type *)0)->member ) *__mptr = (ptr) 這個放在這到底有什麼意義,這個展開後其實就是 int *mptr = ptr;
好像跟我們的主體沒什麼關係,去掉也可以對不對。然而這纔是內核嚴謹的地方,這個地方唯一的作用是驗證參數的類型匹不匹配,如果傳入的參數不匹配,編譯後會有警告信息,幫助程序員更好的定位問題點。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章