核心中鏈表的使用非常廣泛,這裡將linux/list.h中的部分,也是最常用的宏定義給總結了。
Pro-III、核心鏈表:
1、定義+初始化:
#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;
}
2、添加:
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{//[prev]--[new]--[next]
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
static inline void list_add(struct list_head *new, struct list_head *head)
{//將new添加到鏈表頭
__list_add(new, head, head->next);
}
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{//將new添加到鏈表尾
__list_add(new, head->prev, head);
}
3、刪除:
static inline void __list_del(struct list_head * prev, struct list_head * next)
{//[prev]--[del]--[next]
next->prev = prev;
prev->next = next;
}
static inline void list_del(struct list_head *entry)
{//徹底刪除
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1; //指向無效地址
entry->prev = LIST_POISON2;
}
static inline void list_del_init(struct list_head *entry)
{//刪除+初始化
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
4、移動:
static inline void list_move(struct list_head *list, struct list_head *head)
{//將list移到鏈表最前
__list_del(list->prev, list->next);
list_add(list, head);
}
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{//將list移到鏈表最後
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
5、判斷:
static inline int list_is_last(const struct list_head *list,
const struct list_head *head)
{//list是否為最後一個
return list->next == head;
}
static inline int list_empty(const struct list_head *head)
{//鏈表是否為空白
return head->next == head;
}
6、得到結構體:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
//得到MEMBER和TYPE結構體地址之間的差值
#define container_of(ptr, type, member) ({ /
const typeof( ((type *)0)->member ) *__mptr = (ptr); /
//定義一個和membe變數類型一樣的指標__mptr
(type *)( (char *)__mptr - offsetof(type,member) );})
//顯然type結構體的地址肯定比member變數的地址低
//於是減去它們的差值就得到真實type結構體的地址
#define list_entry(ptr, type, member) /
container_of(ptr, type, member)
//得到type結構體的地址
#define list_first_entry(ptr, type, member) /
list_entry((ptr)->next, type, member)
//得到鏈表中第一個節點指標
7、遍曆鏈表:
#define list_for_each(pos, head) /
for (pos = (head)->next; prefetch(pos->next), pos != (head); /
pos = pos->next)
//prefetch是預取記憶體的內容,程式員告訴CPU哪些內容可能馬上用到,CPU預取,用於最佳化。
#define __list_for_each(pos, head) /
for (pos = (head)->next; pos != (head); pos = pos->next)
//顯然,和上面的就差了個預取指令的最佳化
#define list_for_each_prev(pos, head) /
for (pos = (head)->prev; prefetch(pos->prev), pos != (head); /
pos = pos->prev)
//向前遍曆鏈表
#define list_for_each_safe(pos, n, head) /
for (pos = (head)->next, n = pos->next; pos != (head); /
pos = n, n = pos->next)
//安全遍曆,容許有刪除操作發生
//設想,假設採用list_for_each(pos,head),如果將pos給刪除了
//那麼pos=pos->next這條語句就有問題了,pos->next指向一個
//非法的位置(list_del)或者指向了自己(del_del_init),這怎麼能容許
//第一種情況在第二次會直接出錯,因為pos= LIST_POISON1(非法指標)
//第二種情況直接死迴圈,因為pos初始化時將next設定為自己了
#define list_for_each_prev_safe(pos, n, head) /
for (pos = (head)->prev, n = pos->prev; /
prefetch(pos->prev), pos != (head); /
pos = n, n = pos->prev)
//向前的安全遍曆
#define list_for_each_entry(pos, head, member) /
for (pos = list_entry((head)->next, typeof(*pos), member); /
prefetch(pos->member.next), &pos->member != (head); /
pos = list_entry(pos->member.next, typeof(*pos), member))
//在遍曆的過程中直接使用結構體指標
#define list_for_each_entry_reverse(pos, head, member) /
for (pos = list_entry((head)->prev, typeof(*pos), member); /
prefetch(pos->member.prev), &pos->member != (head); /
pos = list_entry(pos->member.prev, typeof(*pos), member))
//向前遍曆
#define list_for_each_entry_continue(pos, head, member) /
for (pos = list_entry(pos->member.next, typeof(*pos), member); /
prefetch(pos->member.next), &pos->member != (head); /
pos = list_entry(pos->member.next, typeof(*pos), member))
//同樣是遍曆,但是這裡的pos是已經存在的結構體指標,也就是可以從任何節點開始遍曆
#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))
//安全遍曆
#define list_for_each_entry_safe_continue(pos, n, head, member) /
for (pos = list_entry(pos->member.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))
//安全遍曆,並且可以任意節點遍曆