學習教程詳解Linux內核數據結構(全)
當使用鏈表接口時, 你應當一直記住列表函數不做加鎖. 如果你的驅動可能試圖對同一個列表并發操作, 你有責任實現一個加鎖方案. 可選項( 破壞的列表結構, 數據丟失, 內核崩潰) 肯定是難以診斷的.
為使用列表機制, 你的驅動必須包含文件 . 這個文件定義了一個簡單的類型 list_head 結構:
以下是代碼片段:
struct list_head { struct list_head *next, *prev; };
真實代碼中使用的鏈表幾乎是不變地由幾個結構類型組成, 每一個描述一個鏈表中的入口項. 為在你的代碼中使用 Linux 列表, 你只需要嵌入一個 list_head 在構成這個鏈表的結構里面. 假設, 如果你的驅動維護一個列表, 它的聲明可能看起來象這樣:
以下是代碼片段:
struct todo_struct
{
struct list_head list;
int priority;
};
列表的頭常常是一個獨立的 list_head 結構. 圖鏈表頭數據結構顯示了這個簡單的 struct list_head 是如何用來維護一個數據結構的列表的.
鏈表頭數據結構
鏈表頭必須在使用前用 INIT_LIST_HEAD 宏來初始化. 一個"要做的事情"的鏈表頭可能聲明并且初始化用:
以下是代碼片段:
struct list_head todo_list;
INIT_LIST_HEAD(&todo_list);
可選地, 鏈表可在編譯時初始化:
以下是代碼片段:
LIST_HEAD(todo_list);
幾個使用鏈表的函數定義在 :
以下是代碼片段:
list_add(struct list_head *new, struct list_head *head);
在緊接著鏈表 head 后面增加新入口項 -- 正常地在鏈表的開頭. 因此, 它可用來構建堆棧. 但是, 注意, head 不需要是鏈表名義上的頭; 如果你傳遞一個 list_head 結構, 它在鏈表某處的中間, 新的項緊靠在它后面. 因為 Linux 鏈表是環形的, 鏈表的頭通常和任何其他的項沒有區別.
以下是代碼片段:
list_add_tail(struct list_head *new, struct list_head *head);
剛好在給定鏈表頭前面增加一個新入口項 -- 在鏈表的尾部, 換句話說. list_add_tail 能夠, 因此, 用來構建先入先出隊列.
以下是代碼片段:
list_del(struct list_head *entry);
list_del_init(struct list_head *entry);
給定的項從隊列中去除. 如果入口項可能注冊在另外的鏈表中, 你應當使用 list_del_init, 它重新初始化這個鏈表指針.
以下是代碼片段:
list_move(struct list_head *entry, struct list_head *head);
list_move_tail(struct list_head *entry, struct list_head *head);
給定的入口項從它當前的鏈表里去除并且增加到 head 的開始. 為安放入口項在新鏈表的末尾, 使用 list_move_tail 代替.
以下是代碼片段:
list_empty(struct list_head *head);
如果給定鏈表是空, 返回一個非零值.
以下是代碼片段:
list_splice(struct list_head *list, struct list_head *head);
將 list 緊接在 head 之后來連接 2 個鏈表.
list_head 結構對于實現一個相似結構的鏈表是好的, 但是調用程序常常感興趣更大的結構, 它組成鏈表作為一個整體. 一個宏定義, list_entry, 映射一個 list_head 結構指針到一個指向包含它的結構的指針. 它如下被調用:
以下是代碼片段:
list_entry(struct list_head *ptr, type_of_struct, field_name);
這里 ptr 是一個指向使用的 struct list_head 的指針, type_of_struct 是包含 ptr 的結構的類型, field_name 是結構中列表成員的名子. 在我們之前的 todo_struct 結構中, 鏈表成員稱為簡單列表. 因此, 我們應當轉變一個列表入口項為它的包含結構, 使用這樣一行:
以下是代碼片段:
struct todo_struct *todo_ptr = list_entry(listptr, struct todo_struct, list);
list_entry 宏定義使用了一些習慣的東西但是不難用.
鏈表的遍歷是容易的: 只要跟隨 prev 和 next 指針. 作為一個例子, 假設我們想保持 todo_struct 項的列表已降序的優先級順序排列. 一個函數來添加新項應當看來如此:
以下是代碼片段:
void todo_add_entry(struct todo_struct *new)
{
struct list_head *ptr;
struct todo_struct *entry;
新文章:
- CentOS7下圖形配置網絡的方法
- CentOS 7如何添加刪除用戶
- 如何解決centos7雙系統后丟失windows啟動項
- CentOS單網卡如何批量添加不同IP段
- CentOS下iconv命令的介紹
- Centos7 SSH密鑰登陸及密碼密鑰雙重驗證詳解
- CentOS 7.1添加刪除用戶的方法
- CentOS查找/掃描局域網打印機IP講解
- CentOS7使用hostapd實現無AP模式的詳解
- su命令不能切換root的解決方法
- 解決VMware下CentOS7網絡重啟出錯
- 解決Centos7雙系統后丟失windows啟動項
- CentOS下如何避免文件覆蓋
- CentOS7和CentOS6系統有什么不同呢
- Centos 6.6默認iptable規則詳解
聯系電話:(0757)22630313、22633833
中華人民共和國增值電信業務經營許可證: 粵B1.B2-20030321 備案號:粵B2-20030321-1
網站公安備案編號:44060602000007 交互式欄目專項備案編號:200303DD003