/**
* container_of - cast a member of a structureout to the containing structure
* @ptr: the pointer to the member.//指向成員變數的指標
* @type: the type of the container struct this is embedded in.//結構體的型別
* @member: the name of the member within the struct.//成員變數名**/
#definecontainer_of(ptr, type, member) ()
每行前面的數字是所在的行數。 可見在這個巨集定義中用到了另外兩個巨集:typeof 和 offsetof 。
對 typeof 的理解:
實際上,
typeof 並不是巨集定義,它是gcc的關鍵字,是gcc特有的特性。
如果只知道乙個變數的名字要得到其型別
,並不是巨集定義能夠完成的,這需要編譯時的資訊。所 以,
typeof 操作是gcc內建的功能
,在核心標頭檔案和glibc標頭檔案中都是找不到typeof的巨集定義的。
對 offsetof 的理解:
offsetof 是乙個真正的巨集,它定義在核心源**
include/linux/stddef.h
檔案中:
第一步得到成員member相對於結構體起始位置的偏移量(就是說相對於結構體的首位址來說往後此成員變數往後偏移了幾個位元組)
24 #define offsetof(type, member) ((size_t) &((type *)0)->member)
在這裡,type表示乙個結構體的型別,member是結構體中的乙個成員變數的名字。offsetof 巨集的作用是計算成員變數 member 相對於結構體起始位置的記憶體偏移量,以位元組(byte)為單位。
它的計算原理是,把整數0進行強制型別轉換,轉換為乙個 type 型別的指標; 然後找到成員變數 member; 最後用
取位址符 「&」 得到 member 的位址
。 因為結構體是從位址0處開始的,所以 member 的位址就是其相對於結構體起始位置的偏移量。
第一步完成
第二步:減法操作
對 container_of 的理解:
三個引數, ptr是成員變數的指標, type是指結構體的型別, member是成員變數的名字。 container_of 的作用就是在已知某乙個成員變數的名字、指標和結構體型別的情況下,計算結構體的指標,也就是計算結構體的起始位址。 計算的方法其實很簡單,就是用該成員變數的指標
減去它相對於結構體起始位置的偏移量。
493 #define container_of(ptr, type, member) ()//減操作
在這個定義中,
typeof( ((type *)0)->member ) 就是獲得 member 的型別, 然後定義了乙個臨時的常量指標 __mptr, 指向 member
變數。 為什麼不直接使用 ptr 而要多此一舉呢? 我想可能是為了避免對 ptr 及prt 指向的內容造成破壞。 把 __mptr 轉換成 char * 型別, 因為 offsetof 得到的偏移量是以位元組為單位。
兩者相減得到結構體的起始位置, 再強制轉換成 type 型別。
實質上
#define container_of(ptr, type, member) ()
如果知道type和member 就能獲取type的首位址,也就是結構體首位址。
container of巨集實現原理
ptr 指向例項化的結構體元素member的指標 type 是這個結構體型別 member 結構體中乙個元素的元素名 1 type 0 member 將0位址定義成乙個type型別指標,這個指標就可以訪問這個型別裡面的任意元素了 2 typeof type 0 member 得到這個元素的資料型別 ...
container of實現原理詳解
container of在核心函式中經常使用,該函式的功能是根據乙個結構體成員的指標,返回這個成員指標所在的結構體的首指標。舉例說明如下 struct std stuct std test int p test.d container of p,stuct std,d 這個函式將返回test變數的首...
container of 函式簡介
在linux 核心程式設計中,會經常見到乙個巨集函式container of ptr,type,member 但是當你通過追蹤原始碼時,像我們這樣的一般人就會絕望了 這一堆都是什麼呀?函式還可以這樣定義?怎麼還有0呢?哎,算了,還是放棄吧。這就是核心大佬們厲害的地方,隨便兩行 就讓我們懷疑人生,凡是...