linux核心之container of )應用

2021-06-23 02:40:00 字數 2080 閱讀 8578

本來不打算寫這篇博文的,因為我覺得在 linux核心之container_of()詳解  文章中已經講的非常詳細了,再寫什麼也覺得是狗尾續貂了,沒必要。可是今天自己做openvswitch核心開發時,發現自己也用錯幾個地方。然後又回想下記得有個博友說過一句話:聰明的作者不僅能自己看懂,還能深入淺出的舉些簡單的例子幫助別人理解。所以就寫個簡單的程式來說明下怎麼使用container_of()這個巨集吧。

這個程式只是用來說明怎麼用container_of()這個巨集,所以在程式中有些細節(動態申請時沒判斷是否申請成功,動態分配的記憶體沒有銷毀等)沒去過多的處理,希望大家諒解。

先來看第30行的**,ptr_a = test_init();這是獲取個int型的指標,聯絡test_init()函式可知也是把結構體變數中int a的位址傳過來。所以記住關鍵點一:ptr_a是結構體變數中的成員a的位址。

再來看第32行的**,t1 = container_of(ptr_a,t,a);這是行最關鍵的**了。這個返回的是指向成員a(ptr_a是a的位址)所在的結構體變數的指標。說下裡面的引數,

第乙個引數:ptr_a   這是個關鍵性引數,因為有ptr_a所以才能和成員a所在的結構體變數聯絡起來。記住這是個結構體成員的位址,而不能認為是個指標,因為如果結構體成員是個指標,那麼這個引數就是指標的位址(二級指標)。再如果這個成員是個結構體變數,那麼這個引數也是結構體變數的位址。記住一定是結構體成員的位址,如果想知道為什麼會這樣,還是請你詳細的分析下這個巨集就知道了(當然了也可以看linux核心之container_of() 詳解);

第二個引數:t,這是結構體變數的型別,這個是一定要這麼填的。

第三個引數:a,很多人會栽在這個引數手上。很多人會這麼寫:t->a或者t.a等等。其實這只要填個與第乙個引數對應的成員變數名就可以,絕對不需要用結構體變數來指向(t->  )。所謂與第乙個變數對應就是說:如果第乙個引數是 &(t->c)  那麼相對於的第三個引數就直接寫  c就可以了。

這個大概的就分析這麼些,下面貼上執行結果:

本來有段工作上出現錯誤的**,但因為是這個涉及到公司的工作所以刪除了。見諒!如果涉及到核心中hlist_for_each_entry(),hlist_for_each_entry_continue(),hlist_for_each_entry_safe()等等,這類巨集的話,就要小心巨集中的 hlist_entry(ptr, type, member)  出問題了,#define hlist_entry(ptr, type, member) container_of(ptr,type,member)  所以總結來說還是要小心使用 container_of()巨集。如果真遇到使用hlist_for_each_entry()這類巨集出錯的話,可以檢視下巨集中呼叫的container_of()是否出錯了,引數是否對了。

了解核心中煉表或者雜湊鍊錶結構的都知道,裡面是沒有資料項的,要我們自己使用時,自行定義資料結構體(如文中的struct  datanode結構體),然後包含核心中定義鍊錶結構體(struct hlist_node *node)。而我們定義的資料結構體(datanode)是靠核心中定義的鍊錶結構體節點(struct hlist_node *node)來連線的(我們對這種鍊錶結構的操作一般都是使用核心設計好的一些操作巨集或者函式,這些巨集或者函式都是對沒有資料項的鍊錶節點進行操作的)。所以一般是已知核心鍊錶節點(struct hlist_node *node)通過container_of() 來求出資料節點(struct  datanode)的頭指標。

問題來了,如果已知資料節點中的成員node是可以推導出datanode指標的。但如果僅僅是知道node所指向的資料,則是不能由container_of()推導出。  (為什麼不能推導出來,稍微看下就知道,因為這樣就相當於是個單鏈表了,單鏈表是無法推出前個節點的位址)而我們程式中操作時,往往是傳遞過來的是某個鍊錶節點也就是node指向的資料。所以這種鍊錶的結構是個誤區,要多小心。

Oracle全文索引之六 附 CONTAINS函式

出處 remark beijing是乙個單詞,要用單引號括起來。remark hebei province是乙個片語,在單引號裡還要用雙引號括起來。remark 可以指定邏輯操作符 包括 and and not,or remark 上面的查詢將返回包含 nanjing road nanjing ea...

Linux之核心模組

linux核心採用的是模組化技術,這樣保證了核心的可維護性和可擴充套件性。模組化設計允許我們在需要時才將某個模組載入到核心,實現動態核心的調整。linux核心模組的命名方式通常為 模組名稱.ko 在centos 7中核心模組被集中儲存在 lib modules目錄下。對核心模組的基本操作 1 檢視核...

linux核心分析之fork c

include include include include include 申明外部呼叫函式,驗證位址所指向的頁面是否可寫 extern void write verify unsigned long address 全域性變數,用於產生可用的程序id long last pid 0 對指定起始...