Use of the Linux kernel list module

Source: Internet
Author: User

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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.