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_POSITION1LIST_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内核链表实现的主要内容,如果未能解决你的问题,请参考以下文章

用单链表实现栈 Push,Pop时间为O

LRU 缓存淘汰算法

Linux内核中双向链表的经典实现

linux内核链表实现

LinkedList 源码分析(JDK 1.8)

Linux内核链表复用实现队列