核心驅動開發第四天linux核心鏈表__linux
來源:互聯網
上載者:User
基本概念
1.鏈表是一種常用的資料結構,它通過指標
將一系列資料節點串連成一條資料鏈。
相
對於數組,鏈表具有更好的動態性,建立
鏈表時無需預Crowdsourced Security Testing道資料總量,可以隨機
分配空間,可以高效地在鏈表中的任意位
置即時插入或刪除資料。
2.鏈表的開銷主要
是訪問的順序性和組織鏈的空間損失
通常鏈表資料結構至少包含兩個域:
資料
域和指標域,資料域用於儲存資料,指標
域用於建立與下一個節點的聯絡。
按照指
針域的組織以及各個節點之間的聯絡形
式,鏈表又可以分為單鏈表、雙鏈表、循
環鏈表等多種類型。
在Linux核心中使用了大量的鏈表結
構來組織資料。這些鏈表大多採用
了[include/linux/list.h]中實現的一
套精彩的鏈表資料結構。
實現:
1.
鏈表資料結構的定義:
struct list_head
{
struct list_head *next, *prev;
};
list_head結構包含兩個指向list_head結構指標
prev和next,
由此可見,核心的鏈表具備雙鏈表功
能,實際上,通常它都組織成雙向迴圈鏈表。
2.
鏈表操作
核心中提供的鏈表操作主要有:
1.初始化鏈表頭
INIT_LIST_HEAD(list_head *head)
2.插入節點
list_add(struct list_head *new, struct list_head *head)
list_add_tail(struct list_head *new, struct list_head *head)
3.刪除節點
list_del(struct list_head *entry)
4.提取資料結構
list_entry(ptr, type, member)
已知資料結構中的節點指標ptr,找出資料結
構,
例:
list_entry(aup, struct autofs, list)
5.遍曆
list_for_each(struc list_head *pos, struc list_head *head)
例:
struct list_head *entry;
struct list_head cs46xx_devs; //鏈表頭
list_for_each(entry, &cs46xx_devs)
{
card = list_entry(entry, struct cs_card, list);
if (card->dev_midi == minor)
break;
}
還有
list_for_each_entry
反向遍曆
list_for_each_entry_reverse()
遍曆的同時刪除
list_for_each_entry_safe()
6.釋放
不能使用list_for_each()和list_del()來釋放鏈表
使用for迴圈和list_del ,然後使用kfree使用kmalloc分配的記憶體
7.移動和合并鏈表
把節點從一個鏈表移動到另一個鏈表
list_move()
list_move_tail()
查空
list_empty()
將兩個鏈表合并起來
list_splice()
將兩個鏈表合并並且重新初始化原來的鏈表
list_splice_init()
核心資料類型
鏈表,隊列kfifo,映射,二叉樹(紅/黑樹狀結構)摘自linux核心設計與實現第三版
資料結構以及選擇
如果對資料集合的主要操作是遍曆資料,就使用鏈表。事實上沒有資料結構可以提供比線性演算法複雜度更好的演算法遍曆元素,所以你應該用最簡單的資料結構完成簡單工作。另外,當效能並非首要考慮因素時,或者當你需要儲存先對較少的資料時,或者當你需要和核心中其他使用鏈表的代碼互動時,請優先選擇鏈表
如果你的代碼符合生產者/消費者模式,則使用隊列,特別是如果你想要一個定長緩衝。隊列會使得添加和刪除工作變得簡單有效。同時隊列也提供了先入先出(FIFO)語義,而這也正是生產者/消費者用例的普遍需求。另一方面,如果你需要儲存一個大小不明的資料集合,那麼鏈表可能更合適,因為你可以添加任何數量的資料項目
如果你需要映射一個UID到一個對象,就使用映射。映射結構使得映射工作簡單有效,而且映射可以幫你維護和分配UID。LINUX的映射介面是針對UID到指標的映射,它並不適合其他情境。但是如果你在處理髮給使用者空間的描述符,就考慮一下映射吧。
如果你需要儲存大量資料,並且檢索迅速,那麼紅/黑樹狀結構最好。紅/黑樹狀結構可確保搜尋時間複雜度是對數關係,同時也能保證按序遍曆時間複雜度是線性關係。雖然他比任何資料結構複雜一些,但其對記憶體開銷情況並不是太糟。但是如果你沒有執行太多次時間緊迫的尋找操作,則紅/黑樹狀結構可能不是最好的選擇,這種情況最好使用鏈表。