核心鍊錶詳解 struct list head

2021-10-25 22:32:47 字數 4471 閱讀 5934

1.自己實現核心鍊錶的部分

2.核心鍊錶使用舉例

#include

struct list_head

;#define list_head_init(name)

#define list_head(name) \

struct list_head name = list_head_init(name)

/*1.向鍊錶中新增節點,普通的在兩個非空結點中插入乙個結點,注意new、prev、next都不能是空值

2.prev可以等於next,此時在只含頭節點的鍊錶中插入新節點。

3.只有頭結點的時候,頭部插入和尾部插入沒有區別

*/static

inline

void

__list_add

(struct list_head *new,

struct list_head *prev,

struct list_head *next)

//頭部插入,插在頭結點之後,

static

inline

void

list_add_head

(struct list_head *new,

struct list_head *head)

//尾部插入,插在最後乙個元素之後

static

inline

void

list_add_tail

(struct list_head *new,

struct list_head *head)

/*從鍊錶中刪除節點

*/static

inline

void

__list_del

(struct list_head * prev,

struct list_head * next)

//刪除entry所指的結點,同時將entry所指向的結點指標域封死

static

inline

void

list_del

(struct list_head *entry)

//移動節點

//將entry所指向的結點移動到head所指向的結點的後面。

static

inline

void

list_move_head

(struct list_head *entry,

struct list_head *head)

//刪除了list所指向的結點,將其插入到head所指向的結點的前面,

//如果head->prev指向鍊錶的尾結點的話,就是將list所指向的結點插入到鍊錶的結尾

static

inline

void

list_move_tail

(struct list_head *entry,

struct list_head *head)

//判斷是否為空鍊錶

//由list-head構成的雙向迴圈鍊錶中,通常有乙個頭節點,其不含有有效資訊,

//初始化時prev和next都指向自身。判空操作是判斷除了頭節點外是否有其他節點。

//試煉表是否為空,如果是只有乙個結點,head,head->next,head->prev都指向同乙個結點,則這裡會返回1,

//表示空;但這個空不是沒有任何結點,

//而是只有乙個頭結點,因為頭節點只是純粹的list節點,沒有有效資訊,故認為為空

static

inline

intlist_empty

(const

struct list_head *head)

static

inline

intlist_empty_careful

(const

struct list_head *head)

//鍊錶合併

static

inline

void

__list_splice

(struct list_head *list,

struct list_head *head)

static

inline

void

list_splice

(struct list_head *list,

struct list_head *head)

/*type:大結構體的型別

member:大結構體中成員的名稱

*/#define offsetof(type, member) ((size_t) &((type *)0)->member)

/*作用:通過成員的指標找到大結構體的指標

ptr 結構體成員的指標

type 大結構體的型別

member ptr代表的成員在大結構體的名稱

*/#define container_of(ptr, type, member) ()

//鍊錶遍歷

#define __list_for_each(pos, head) \

for (pos = (head)->next; pos != (head); pos = pos->next)

#define list_for_each_safe(pos, n, head) \

for (pos = (head)->next, n = pos->next; pos != (head); \

pos = n, n = pos->next)

#define list_entry(ptr, type, member) \

container_of(ptr, type, member)

/*pos:大結構體的指標

head:頭結點

member: struct list_head 在大結構體中的名稱

*/#define list_for_each_entry(pos, head, member) \

for (pos = list_entry((head)->next, typeof(*pos), member); \

&pos->member != (head); \

pos = list_entry(pos->member.next, typeof(*pos), member))

//相比於list_for_each_entry,list_for_each_entry_safe用指標n對鍊錶的下乙個資料結構進行了臨時儲存,

//所以如果在遍歷鍊錶的時候需要做刪除鍊錶中的當前項操作時,用list_for_each_entry_safe可以安全的刪除,

//而不會影響接下來的遍歷過程(用n指標可以繼續完成接下來的遍歷, 而list_for_each_entry則無法繼續遍歷,

//刪除後會導致無法繼續遍歷)

/*pos:大結構體的指標

n:大結構體的指標,是乙個備份

head:頭結點

member: struct list_head 在大結構體中的名稱

*/#define list_for_each_entry_safe(pos, n, head, member) \

for (pos = list_entry((head)->next, typeof(*pos), member), \

n = list_entry(pos->member.next, typeof(*pos), member); \

&pos->member != (head); \

pos = n, n = list_entry(n->member.next, typeof(*n), member))

struct student

;int

main

(int argc,

char

const

*ar**)

;struct student sta =};

struct student stb =};

struct student stc =};

struct student std =};

list_add_tail

(&sta.entry,

&list_head_obj)

;list_add_tail

(&stb.entry,

&list_head_obj)

;list_add_tail

(&stc.entry,

&list_head_obj)

;list_add_head

(&std.entry,

&list_head_obj)

;list_for_each_entry

(pos_st,

&list_head_obj, entry)

list_for_each_entry_safe

(pos_st, pos_n,

&list_head_obj, entry)

return0;

}

Linux核心通用鍊錶詳解

linux核心中充斥著大量的資料結構,這些資料結構很多都是使用結構體來表示 如cdev結構體用於描述乙個字元裝置,再如task struct結構體,是我們所說的程序控制塊pcb,用於描述乙個程序的所有資訊。追尋核心原始碼我們會發現很多都是表示裝置的結構體中都有list head這樣的字段,沒錯這就是...

Linux中的核心鍊錶例項詳解

linux中的核心鍊錶例項詳解 鍊錶中一般都要進行初始化 插入 刪除 顯示 釋放鍊錶,尋找節點這幾個操作,下面我對這幾個操作進行簡單的介紹,因為我的能力不足,可能有些東西理解的不夠深入,造成一定的錯誤,請各位博友指出。a linux核心鍊錶中的幾個主要函式 下面是核心中的原始碼拿出來給大家分析一下 ...

核心hlist鍊錶

出處 核心中的定義 struct hlist head struct hlist node 這個資料結構與一般的hash list資料結構定義有以下的區別 1 首先,hash的頭節點僅存放乙個指標,也就是first指標,指向的是list的頭結點,沒有tail指標也就是指向list尾節點的指標,這樣的...