Linux内核中链表list_head常见使⽤⽅法
list_head 定义
list_head 结构体定义,kernel/inclue/linux/types.h  如下:
1. struct list_head {
2. struct list_head *next, *prev;
3. };
然后就开始围绕这个结构开始构建链表,然后插⼊、删除节点 ,遍历整个链表等等,其实内核已经提供好了现成的接⼝,接下来就让我们进⼊ kernel/include/linux/list.h中:
⼀. 创建链表
内核提供了下⾯的这些接⼝来初始化链表:
1. #define LIST_HEAD_INIT(name) { &(name), &(name) }
2. #define LIST_HEAD(name) \
3. struct list_head name = LIST_HEAD_INIT(name)
4. static inline void INIT_LIST_HEAD(struct list_head *list)
5. {
6. WRITE_ONCE(list->next, list);
7. list->prev = list;
8. }
所以可以通过这个⽅法来初始化⼀个链表,如下是将listhead作为⼀个结构体成员存放了,为什么要这么做呢?后⾯在实际的例⼦应⽤中会使⽤到struct data_list {
int data_len;
char buf[64];
list_node;
struct list_head list_node
};
struct data_list * iic_data_head;
iic_data_head = malloc(sizeof(struct data_list ));
memset(iic_data_head, 0x0, sizeof(struct data_list ));
if (!iic_data_head) {
KLOGD("no mem\n");
return -ENOMEM;
}
list_node);
INIT_LIST_HEAD(&iic_data_head->list_node
⼆. 添加节点
内核已经提供了添加节点的接⼝了
1.  list_add
如下所⽰。 根据注释可知,是在链表头head后⽅插⼊⼀个新节点new。
1. /**
2. * list_add - add a new entry
3. * @new: new entry to be added
4. * @head: list head to add it after
5. *
6. * Insert a new entry after the specified head.
7. * This is good for implementing stacks.
8. */
9. static inline void list_add(struct list_head *new, struct list_head *head)
10. {
11. __list_add(new, head, head->next);
12. }
list_add再调⽤__list_add接⼝
1. /*
2. * Insert a new entry between two known consecutive entries.
3. *
4. * This is only for internal list manipulation where we know
5. * the prev/next entries already!
6. */
7. static inline void __list_add(struct list_head *new,
8. struct list_head *prev,
9. struct list_head *next)
10. {
11. if (!__list_add_valid(new, prev, next))
12. return;
13. next->prev = new;
14. new->next = next;
15. new->prev = prev;
16. WRITE_ONCE(prev->next, new);
17. }
其实就是在head 链表头后和链表头后第⼀个节点之间插⼊⼀个新节点。然后这个新的节点就变成了链表头后的第⼀个节点了。
2. list_add_tail 接⼝
上⾯所讲的list_add接⼝是从链表头header后添加的节点。 同样,内核也提供了从链表尾处向前添加节点的接⼝list_add_tail. 让我们来看⼀下它的具体实现。
1. /**
2. * list_add_tail - add a new entry
3. * @new: new entry to be added
4. * @head: list head to add it before
5. *
6. * Insert a new entry before the specified head.
7. * This is useful for implementing queues.
8. */
9. static inline void list_add_tail(struct list_head *new, struct list_head *head)
10. {
11. __list_add(new, head->prev, head);
12. }
进⼀步把__list_add ()展开如下:
1. /*
2. * Insert a new entry between two known consecutive entries.
3. *
4. * This is only for internal list manipulation where we know
5. * the prev/next entries already!
6. */
7. static inline void __list_add(struct list_head *new,
8. struct list_head *prev,
9. struct list_head *next)
10. {
11. if (!__list_add_valid(new, prev, next))
12. return;
13. next->prev = new;
14. new->next = next;
15. new->prev = prev;
16. WRITE_ONCE(prev->next, new);
17. }
所以,很清楚明了, list_add_tail就相当于在链表头前⽅依次插⼊新的节点(也可理解为在链表尾部开始插⼊节点,此时,header节点既是为节点,保持不变)
三. 删除节点
内核同样在list.h⽂件中提供了删除节点的接⼝ list_del(), 让我们看⼀下它的实现流程
1. static inline void list_del(struct list_head *entry)
2. {
3. __list_del_entry(entry);
4. entry->next = LIST_POISON1;
5. entry->prev = LIST_POISON2;
6. }
1. /*
2. * Delete a list entry by making the prev/next entries
3. * point to each other.
4. *
5. * This is only for internal list manipulation where we know
6. * the prev/next entries already!
7. */
8. static inline void __list_del(struct list_head * prev, struct list_head * next)
9. {
10. next->prev = prev;
11. WRITE_ONCE(prev->next, next);
12. }
13. /**
14. * list_del - deletes entry from list.
15. * @entry: the element to delete from the list.
16. * Note: list_empty() on entry does not return true after this, the entry is
17. * in an undefined state.
18. */
19. static inline void __list_del_entry(struct list_head *entry)
20. {
21. if (!__list_del_entry_valid(entry))
22. return;
23. __list_del(entry->prev, entry->next);
typeof的用法
24. }
利⽤list_del(struct list_head *entry) 接⼝就可以删除链表中的任意节点了,但需注意,前提条件是这个节点是已知的,既在链表中真实存在,切prev,next指针都不为NULL。
四. 链表遍历
内核是同过下⾯这个宏定义来完成对list_head链表进⾏遍历的,如下 :
1. /**
2. * list_for_each - iterate over a list
3. * @pos: the &struct list_head to use as a loop cursor.
4. * @head: the head for your list.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。