The list module is a set of cyclic linked list functions provided by the Linux kernel, and the header file is:<linux/list.h>.
main data Structure :
struct List_head {struct list_head *next, *prev;};
This is a doubly linked list.
#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;}
You must initialize a linked header before using it, and you can use the following macro to directly define and initialize a linked table header:
List_head (name)
The macro parameter name is the name of the linked header definition.
For example:
List_head (Listhead)
When using the methods in the list module, you must include struct List_head class members in your data structure, for example:
Struct mynode{ Int A; Struct list_head ListNode;}; Struct Mynode Nodevar;
Insert operation
/* * Insert A new entry between, known consecutive entries. * * This was only for internal list manipulation where we know * the Prev/next entries already! */#ifndef config_debug_liststatic inline void __list_add (struct list_head *new, struct list_h EAD *prev, struct list_head *next) {next->prev = new; New->next = Next; New->prev = prev; Prev->next = new;} #elseextern void __list_add (struct list_head *new, struct list_head *prev, struct List_head *next); #endif/** * List_add-add A new entry * @new: new entry to be added * @head: List head To add it after * Insert a new entry after the specified head. * This is good for implementing stacks. */#ifndef config_debug_liststatic inline void list_add (struct list_head *new, struct list_head *head) {__list_add (n EW, head, head->next);} #elseextern void List_add (struct list_head *new, struct list_head *head); #endif
Call the List_add function to add a data node to the list.
List_add (&nodevar->listnode,&listhead)
Adds an element to the first position of the linked list, the next position of the listhead of the linked header.
/** * List_add_tail-add A new entry * @new: new entry to being added * @head: List head to add it before * * Insert a new E Ntry before the specified head. * This was useful for implementing queues. */static inline void List_add_tail (struct list_head *new, struct list_head *head) { __list_add (new, Head->prev, Head);}
List_add_tail (&nodevar->listnode,&listhead);
In fact, it's putting the listnode element in Nodevar into the end of the list.
Delete operation
/* * Delete a list entry by making the Prev/next entries. * * This was only for internal list manipulation where we know * the Prev/next entries already! */static inline void __list_del (struct list_head * prev, struct list_head * next) { Next->prev = prev; Prev->next = Next;} /** * list_del-deletes entry from list. * @entry: The element to delete from the list. * Note:list_empty on entry does no return true after this, the entry was * in a undefined state. */#ifndef config_debug_liststatic inline void List_del (struct list_head *entry) { __list_del (Entry->prev, Entry->next); Entry->next = List_poison1; Entry->prev = List_poison2;} #elseextern void List_del (struct list_head *entry); #endif
Find Operations
#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_ENTRY (PTR, type, member) container_of (PTR, Type, member)
Where Pos is a staged struct pointer, member is the struct LISTHEAD structure variable inside the struct, and head is the chain header. Container_of () See final note.
If there are n struct Mynode variables added to the list, find the node of element a =100 the operation as follows
Struct mynode* poslist_for_each_entry (Pos, &listhead,listnode) { If (pos->a==) { ... }}
If a pointer memory operation is involved in POS, such as release, you can use the function:
/** * 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 l Ist_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))
This function uses N to save the value of the POS, lest the POS will continue to operate after the POS has caused a memory error.
Example:
Struct mynode* CPos, Npos;list_for_each_entry_safe (CPos, NPos, &listhead, ListNode) {List_del (CPos); free (cPos);}
Note:
Container_of (PTR, type, member) is the pointer to a variable of a domain member in a struct variable to get pointers to variables of the entire struct body.
Example: container_of (&nodevar->listnode, struct mynode, ListNode)
will be the address of the Nodevar.
about thecontainer_ofSeekernel.hin:
/*** Container_of-cast a member of a structure out to the containing structure* @ptr: The pointer to the member.* @t Ype: The type of the container struct This is embedded in.* @member: The name of the member within the struct.**/# Define CONTAINER_OF (PTR, type, member) ({ / const typeof (((type *) 0)->member) *__mptr = (PTR); / (Type *) ((char *) __mptr-offsetof (Type,member));})
Container_of is widely used in Linux kernel to obtain the entry address of a member in a structure.
about theOffsetofSeestddef.hin:
#define OFFSETOF (Type, MEMBER) ((size_t) & ((TYPE *) 0)->member
TYPEis astructof type, 0is an imaginaryTYPEtypeStruct,memberis thestructa member of the. since thestructthe base site is0, MEMBERthe address is the member relative to thestructthe offset of the header address.
about thetypeof,this isGCCof theClanguage extension reserved words,used to declare variable types。
Const typeof ((type *) 0->member) *__mptr = (PTR);It means to declare amemberpointer constants of the same type*__mptr,and initialized toptr.
(Type *) ((char *) __mptr-offsetof (type,member));means that__mptrthe address minusmemberin thatstructThe offset in the resulting address,and convert it intotypeType pointer,the pointer ismember's entry address.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Use of the Linux kernel list module