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尾節點的指標,這樣的...