Linux內(nèi)核鏈表深度剖析

~~~~~Linux內(nèi)核鏈表是Linux內(nèi)核最經(jīng)典的數(shù)據(jù)結(jié)構(gòu)之一夷蚊,Linux內(nèi)核鏈表最大的優(yōu)點就是節(jié)省內(nèi)存拦耐,對鏈表的各項操作較快弯蚜,實現(xiàn)的思路耳目一新,而且在Linux內(nèi)核里頻繁使用攻锰,比如:內(nèi)存管理晾嘶,進程調(diào)度等。
~~~~~Linux內(nèi)核鏈表是一個雙向循環(huán)鏈表娶吞,核心思想就是把鏈表結(jié)點放在數(shù)據(jù)結(jié)點里面垒迂,通過前后指針分別指向前后數(shù)據(jù)結(jié)點里面的鏈表結(jié)點,這樣就可以將各個數(shù)據(jù)結(jié)點連接在一起妒蛇。

一机断、鏈表結(jié)點定義

struct list_head {
    struct list_head *next, *prev;
};

二、內(nèi)核鏈表初始化

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
    struct list_head name = LIST_HEAD_INIT(name)

static inline void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list;
    list->prev = list;
}

INIT_LIST_HEAD函數(shù)prev指針和next指針指向鏈表頭結(jié)點绣夺。LIST_HEAD_INIT宏初始化鏈表頭結(jié)點next指針和prev指針保存頭結(jié)點地址吏奸,實際上和INI_LIST_HEAD函數(shù)初始化效果一樣,LIST_HEAD宏就是鏈表結(jié)點的完整初始化陶耍。我們以實際代碼為例:

struct list_head list;
LIST_HEAD(list);              //list = {&list, &list}

三奋蔚、內(nèi)核鏈表插入結(jié)點

/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next)
{
    next->prev = new;
    new->next = next;
    new->prev = prev;
    prev->next = new;
}
#else
extern void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next);
#endif

/**
 * list_add - add a new entry
 * @new: new entry to be added
 * @head: list head to add it after
 *
 * Insert a new entry after the specified head.
 * This is good for implementing stacks.
 */
#ifndef CONFIG_DEBUG_LIST
static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}
#else
extern void list_add(struct list_head *new, struct list_head *head);
#endif
/**
 * list_add_tail - add a new entry
 * @new: new entry to be added
 * @head: list head to add it before
 *
 * Insert a new entry before the specified head.
 * This is useful for implementing queues.
 */
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}

~~~~我們作圖解釋會更容易理解內(nèi)核鏈表插入操作。
直接看代碼我們即可知道內(nèi)核鏈表實際上采用的是尾插法烈钞,并且有一個頭結(jié)點泊碑。
內(nèi)核鏈表插入結(jié)點前如圖1所示:

插入結(jié)點前.PNG

圖1

內(nèi)核鏈表插入結(jié)點后如圖2所示:


插入結(jié)點后.PNG

~~~~結(jié)合list_add_tail函數(shù)分析可知,假設(shè)鏈表list插入結(jié)點node毯欣,則next=list->next馒过,prev=list;再調(diào)用__list_add則可將新結(jié)點插入到鏈表里面。

四酗钞、內(nèi)核鏈表刪除結(jié)點

/*
 * Delete a list entry by making the prev/next entries
 * point to each other.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
    next->prev = prev;
    prev->next = next;
}

/**
 * list_del - deletes entry from list.
 * @entry: the element to delete from the list.
 * Note: list_empty() on entry does not return true after this, the entry is
 * in an undefined state.
 */
#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    entry->next = LIST_POISON1;
    entry->prev = LIST_POISON2;
}
#else
extern void list_del(struct list_head *entry);
#endif

~~~~直接分析代碼可知腹忽,刪除結(jié)點實際上就是將目標結(jié)點后面一個結(jié)點的前向指針指向目標結(jié)點的前向結(jié)點,目標結(jié)點的前向結(jié)點的后向指針指向目標結(jié)點的后向結(jié)點砚作,這樣就可以把目標結(jié)點分離出來了窘奏。

結(jié)尾

~~~~Linux內(nèi)核鏈表還有很多有意思的實現(xiàn),例如遍歷葫录,獲取數(shù)據(jù)結(jié)點結(jié)構(gòu)體首地址等蔼夜,下一章再詳細分析。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末压昼,一起剝皮案震驚了整個濱河市求冷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌窍霞,老刑警劉巖匠题,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異但金,居然都是意外死亡韭山,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門冷溃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钱磅,“玉大人,你說我怎么就攤上這事似枕「堑” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵凿歼,是天一觀的道長褪迟。 經(jīng)常有香客問我,道長答憔,這世上最難降的妖魔是什么味赃? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮虐拓,結(jié)果婚禮上心俗,老公的妹妹穿的比我還像新娘。我一直安慰自己蓉驹,他們只是感情好城榛,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著戒幔,像睡著了一般吠谢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上诗茎,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天工坊,我揣著相機與錄音,去河邊找鬼敢订。 笑死王污,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的楚午。 我是一名探鬼主播昭齐,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼矾柜!你這毒婦竟也來了阱驾?” 一聲冷哼從身側(cè)響起就谜,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎里覆,沒想到半個月后丧荐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡喧枷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年虹统,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片隧甚。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡车荔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出戚扳,到底是詐尸還是另有隱情忧便,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布咖城,位于F島的核電站茬腿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏宜雀。R本人自食惡果不足惜切平,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辐董。 院中可真熱鬧悴品,春花似錦、人聲如沸简烘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽孤澎。三九已至届氢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間覆旭,已是汗流浹背退子。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留型将,地道東北人寂祥。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像七兜,于是被迫代替她去往敵國和親丸凭。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359