There are a number of linked lists used in the Linux kernel: doubly linked lists. The management of the processes used in the kernel is achieved through a doubly linked list. So the operation of the list is very common and very important, so the kernel by providing a common method to help us to facilitate the implementation of the double-linked list of various operations.
struct List_head {struct list_head *next, *prev;}
0, function to initialize an item in a doubly linked list: Init_list_head (struct list_head *entry)
Init_list_head () Implementation method:
static inline void Init_list_head (struct list_head *entry)
{
Entry->next = entry;
Entry->prev = entry;
}
1, the initialization of the doubly-linked header node: list_head (name);
How to implement List_head:
#define INIT_LIST_HEAD (name) {& (name),& (name)}
#define LIST_HEAD (name) \
struct List_head name = Init_list_head (name)
To see how to use:
static int __init list_head_init (void)
{
List_head (name);
}
At compile time, the above code is translated by the compiler into the following form code:
static int __init list_head_init (void)
{
struct List_head name = {&name,&name};
}
2, adding elements to the head of the doubly linked list operation: List_add (struct list_head *new, struct list_head *head)
The List_add () function is used to implement the addition of an element to the head node of a doubly linked list, which can be used to implement the operation of the stack in the data structure, adding a new data to the top of the stack each time;
List_add (struct list_head *new, struct list_head *head) Implementation method:
static inline void List_add (struct list_head *new, struct list_head *head)
{__list_add (new, head,head->next);}
From an object-oriented point of view: List_add is the encapsulation of __list_add, so let's look at how __list_add through the operation of the doubly linked list to implement the stack operation.
static inline void __list_add (struct list_head *new, struct list_head *prev,
struct List_head *next)
{
New->next = Next; New->next points to the original first node in a doubly linked list;
New->prev = prev; New->prev points to the head node of the doubly linked list;
Prev->next = new; The head node of the double-line linked list points to the new node;
Next->prev = new; The original first node of the doubly linked list points to the new node;
}
3, the tail of the doubly linked list adds elements to the operation: List_add_tail (struct List_head *new,
struct List_head *head)
The List_add_tail () function is used to implement the addition of an element to the tail of a two-strand list, which can be used to implement a queue operation in a data structure, adding a new data to the tail of the queue each time;
List_add_tail (struct list_head *new, struct list_head *head) Implementation method:
static inline void List_add_tail (struct list_head *new, struct list_head *head)
{__list_add (new, Head->prev, head);}
The same list_add_tail () is also the encapsulation of L __list_add ();
4, the operation to delete a data in a doubly linked list: List_del (struct list_head *entry)
Static List_del (struct List_head *entry)
{
__list_del (Entry->prev, Entry->next);
Entry->next = NULL;
Entry->prev = NULL;
}
static inline void __list_del (struct list_head *prev, struct list_head *next)
{
Prev->next = Next;
Next->prev = prev;
}
5. Delete a node in a doubly linked list and initialize it: list_del_init (struct list_head *entry)
static inline void List_del_init (struct list_head *entry)
{
__list_del (Entry->prev, Entry->next);
Init_list_head (entry); Equivalent to Entry->next = entry; Entry->prev = entry;
}
6, replace one of the old data in the doubly linked list with a new data: List_replace (struct List_head *old,
struct List_head *new)
static inline void List_replace (struct list_head *old, struct list_head *new)
{
New->next = old->next;
New->prev = old->prev;
Old->next->prev = new;
Old->prev->next = new;
}
7, replace one of the old data in the doubly linked list with a new data and initialize the old data:
Static inline List_replace_init (struct list_head *old, struct list_head *new)
{
List_replace (old, new);
Init_list_head (old);
}
8, move one of the data in the doubly linked list before the first element of another doubly linked list:
static inline void List_move (struct list_head *entry, struct list_head *head)
{
__list_del (Entry->prev, Entry->next); Remove the entry from the doubly linked list;
List_add (entry, head); Adding entry to the head doubly linked list;
}
9, move one of the data in the doubly linked list to the end of another doubly linked list:
static inline void List_move_tail (struct list_head *entry, struct list_head *head)
{
__list_del (Entry->prev, Entry->next);
List_add_tail (Entry,head);
}
10, test whether a doubly linked list is empty: List_empty (struct list_head *head)
static inline int list_empty (struct list_head *head)
{
return head->next = = head;
}
If the list is empty, List_empty () returns 1, otherwise 0;
11, test whether a data in a doubly linked list is at the end of a doubly linked list:
Static inline List_is_last (struct list_head *entry, struct list_head *head)
{
return entry->next = = head;
}
If a data is at the end of a doubly linked list, then List_is_last () returns 1, otherwise 0 is returned;
12, cut a doubly linked list from one of the items and split it into two separate doubly linked lists:
static inline void list_cut_position (struct head_list *list, struct head_list *entry,
struct head_list *head);
Parameter description: List is the head of the linked list separated from the head doubly linked list;
Entry is the dividing point of the head of the doubly linked list;
List_cut_position () is the encapsulation of the static inline void __list_cut_position ();
Take a look at how __list_cut_position () cuts the doubly linked list:
static inline void __list_cut_position (struct list_head *list,struct list_head *entry,
struct List_head *head)
{
struct List_head *new_first = entry->next; Determine the back data of the entry;
List->next = Head->next; The list points to the first of the original head doubly linked list;
List->next->prev = list; The first item in the original head doubly linked list points to list;
List->prev = entry;
Entry->next = list;
Head->next = New_first;
New_first->prev = head;
}
Summary: List_head (entry);
Init_list_head (struct list_head *entry);
List_add (struct list_head *new, struct list_head *head);
List_add_tail (struct list_head *new, struct list_head *head);
List_del (struct list_head *entry);
List_del_init (struct list_head *entry);
List_replace (struct list_head *old, struct list_head *new);
List_replace_init (struct list_head *old, struct list_head *new);
List_move (struct list_head *entry, struct list_head *head);
List_move_tail (struct list_head *entry, struct list_head *head);
List_empty (struct list_head *head);
List_is_last (struct list_head *entry, struct list_head *head);
List_cut_position (struct list_head *list, struct list_head *entry,
struct List_head *head);
This article is from the "FAI Aberdeen" blog, please make sure to keep this source http://weiguozhihui.blog.51cto.com/3060615/1565131
Operation function of bidirectional linked list in Linux kernel