我知道宏在做什麼。什麼時候使用container_of宏?
在許多內核級代碼中,它通常用於遍歷鏈表。
我想找到其他有用的案例。
何時使用container_of或CONTAINING_RECORD宏?
這個宏何時非常有用?
我知道宏在做什麼。什麼時候使用container_of宏?
在許多內核級代碼中,它通常用於遍歷鏈表。
我想找到其他有用的案例。
何時使用container_of或CONTAINING_RECORD宏?
這個宏何時非常有用?
container_of
,可以忽略指向父s到簡化你的數據結構tructures。
它在鏈表實現中使用,以便列表節點可以是任何結構的元素,並且任何人都可以在不帶有顯式指針的情況下找到父結構。
另一個例子是struct work_struct
。一個workqueue工作函數接收一個work_struct作爲參數,並且它曾經有一個通用的「數據」有效載荷。該數據值爲removed,使結構更小,因爲工作函數可以調用container_of
來查找其父結構。
這是一種解決C沒有泛型或模板這一事實的方法。
你想要一個通用的鏈表,所以你只需要把指針放在節點本身(這樣你就可以抽象出結構本身的管理),然後用CONTAINING_RECORD
找到你自己代碼中的其餘數據如:
struct Node { struct Node *prev, *next; }
//Now you can define functions that operate on a generic struct Node*
struct Item
{
int myData;
struct Node* node; //this would point to the 'node' member of another Item
}
現在,給定一個struct Node
,你可以找到它的Item
說:
CONTAINING_RECORD(ptr, Item, node)
它將指向結構成員的指針調整爲指向包含結構的指針;這在內核中以各種方式使用,最常見的可以被描述爲具有靜態偏移的向下轉換,其中外部結構是從內部派生(通過包含),並且調用者在內部對象上調用方法,即然後分派給外部對象上的方法。
那麼,沒有來自編譯器的OO支持。
對於未來搜索器(R)S:這是我迄今發現的最好的解釋:
http://psomas.wordpress.com/2009/07/01/weird-kernel-macros-container_of/
基本上(報價):
「現在我們可以理解(至少部分)這個宏是做什麼的,它聲明一個指向結構成員ptr
指向的指針,並減去它來自struct ‘instance’(ie __mptr)
的成員的實際地址。 (char *)__mptr
強制轉換是必要的,因此「指針算術」將按預期工作,即從__mptr
減去offsetof
「返回」的(size_t)
字節。「
,並且還另外兩個顯著提示(報價):
」在這一點上,我真的不明白,爲什麼我們不能直接使用PTR指針。我們可以ommit第一線,和宏可能是
#define container_of(ptr, type, member) (type *)((char *)(ptr) - offsetof(type,member))
ptr
只使用一次 - 我們並不需要擔心的副作用。 也許這只是一個良好的編碼實踐「
,並在原來的職位(報價)的後來編輯:
」。顯然,第一行是有‘類型檢查’。它確保type
有一個名爲member
的成員(但我認爲這也是由offsetof
宏完成的),並且如果ptr
不是指向正確類型(member
的類型)的指針,編譯器將打印警告, 。這對於調試運行有用」
給定名爲'結構NODE''ptr',我想你的意思是:'CONTAINING_RECORD(PTR,項目,節點)' – 2011-02-28 17:13:29
哎呀呀,謝謝你,我會改變它 – Mehrdad 2011-02-28 17:14:04
不會是CONTAINING_RECORD(ptr,struct Item,node)嗎? – 2012-09-10 14:53:51