linux内核链表实现
Posted Ven_J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux内核链表实现相关的知识,希望对你有一定的参考价值。
linux内核链表实现
内核实现的是双向循环链表,提供了链表操作的基本功能。
(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;
LIST_HEAD宏创建一个链表头结点,并用LIST_HEAD_INIT宏对头结点进行赋值,使得头结点的前驱和后继指向自己。
INIT_LIST_HEAD函数对链表进行初始化,使得前驱和后继指针指针指向头结点。
(2)插入节点
//在prev和next之间插入新的节点new
1 static inline void __list_add(struct list_head *new,
2 struct list_head *prev,
3 struct list_head *next)
4
5 next->prev = new;
6 new->next = next;
7 new->prev = prev;
8 prev->next = new;
9
10 /*在指定链表的head节点后插入new结点*/
11 static inline void list_add(struct list_head *new, struct list_head *head) 12 13 __list_add(new, head, head->next); 14 15 /*在指定链表的head节点前插入new结点*/
16 static inline void list_add_tail(struct list_head *new, struct list_head *head)
17
18 __list_add(new, head->prev, head);
19
插入节点分为从链表头部插入list_add和链表尾部插入list_add_tail,通过调用__list_add函数进行实现,head->next指向之一个节点,head->prev指向尾部节点。
(3)删除节点
1 static inline void __list_del(struct list_head * prev, struct list_head * next)
2 3 next->prev = prev; 4 prev->next = next; 5 6 /*从链表中删除指定的entry元素。该函数不会释放entry或者释放包含entry的数据结构体所占用的内存*/
7 static inline void list_del(struct list_head *entry)
8
9 __list_del(entry->prev, entry->next);
10 entry->next = LIST_POISON1;
11 entry->prev = LIST_POISON2;
12
从链表中删除一个节点,需要改变该节点前驱节点的后继结点和后继结点的前驱节点。最后设置该节点的前驱节点和后继结点指向LIST_POSITION1和LIST_POSITION2两个特殊值,这样设置是为了保证不在链表中的节点项不可访问,对LIST_POSITION1和LIST_POSITION2的访问都将引起页故障
/*
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized list entries.
*/
#define LIST_POISON1 ((void *) 0x00100100 + POISON_POINTER_DELTA)
#define LIST_POISON2 ((void *) 0x00200200 + POISON_POINTER_DELTA)
(4)移动节点
1 /**
2 * list_move - delete from one list and add as another's head
3 * @list: the entry to move
4 * @head: the head that will precede our entry
5 * 从一个链表中移除list项,然后将其加入到另一列表的head结点后面 6 */ 7 static inline void list_move(struct list_head *list, struct list_head *head) 8 9 __list_del(list->prev, list->next); 10 list_add(list, head); 11 12 13 /** 14 * list_move_tail - delete from one list and add as another's tail 15 * @list: the entry to move 16 * @head: the head that will follow our entry
17 * 从一个链表中移除list项,然后将其加入到另一列表的head结点前 18 */ 19 static inline void list_move_tail(struct list_head *list, 20 struct list_head *head) 21 22 __list_del(list->prev, list->next); 23 list_add_tail(list, head); 24
move将一个节点移动到头部或者尾部。
(5)判断链表
1 /**
2 * list_is_last - tests whether @list is the last entry in list @head
3 * @list: the entry to test
4 * @head: the head of the list
5 */
6 static inline int list_is_last(const struct list_head *list,
7 const struct list_head *head)
8
9 return list->next == head;
10
11
12 /**
13 * list_empty - tests whether a list is empty
14 * @head: the list to test.
15 */
16 static inline int list_empty(const struct list_head *head)
17
18 return head->next == head;
19
list_is_last函数判断节点是否为末尾节点,list_empty判断链表是否为空。
(6)遍历链表
1 /**
2 * list_entry - get the struct for this entry
3 * @ptr: the &struct list_head pointer.
4 * @type: the type of the struct this is embedded in.
5 * @member: the name of the list_struct within the struct.
6 */
7 #define list_entry(ptr, type, member) \\
8 container_of(ptr, type, member)
9
10 /**
11 * list_first_entry - get the first element from a list
12 * @ptr: the list head to take the element from.
13 * @type: the type of the struct this is embedded in.
14 * @member: the name of the list_struct within the struct.
15 *
16 * Note, that list is expected to be not empty.
17 */
18 #define list_first_entry(ptr, type, member) \\
19 list_entry((ptr)->next, type, member)
20
21 /**
22 * list_for_each - iterate over a list
23 * @pos: the &struct list_head to use as a loop cursor.
24 * @head: the head for your list.
25 */
26 #define list_for_each(pos, head) \\
27 for (pos = (head)->next; prefetch(pos->next), pos != (head); \\
28 pos = pos->next)
宏list_entity获取链表的结构,包括数据域。list_first_entry获取链表第一个节点,包括数据源。list_for_each宏对链表节点进行遍历。
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
* 遍历链表
*/
#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))
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop counter.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
* 安全遍历
*/
#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_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
* 遍历的时候同时删除
*/
#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))
list_for_each_entry_reverse(pos, head, member)
//反向遍历链表
list_for_each_entry_safe_reverse(pos, n, head, member)
//反向遍历同时删除以上是关于linux内核链表实现的主要内容,如果未能解决你的问题,请参考以下文章