linux核心學習(17)核心編程基本功之核心鏈表list_entry

來源:互聯網
上載者:User

核心中鏈表的使用非常廣泛,這裡將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))

//安全遍曆,並且可以任意節點遍曆

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.