Linux driver programming step-by-step (11)

Source: Internet
Author: User
Linux Kernel linked list (2)

I previously described how to create a kernel linked list (init_list_head) and add a node (list_add) to the linked list to delete a linked list node (list_del) to obtain the struct (list_entry) corresponding to a linked list node.

Next we will introduce several operations

Replace a linked list node, merge two linked lists, and divide a linked list into two segments, with a hierarchical link.

Replace linked list nodes

Replace a node is easy to understand, that is, replacing the old node with the new node, pointing the corresponding Prev and next pointer of the new node to the prev and next of the old node. Then, point the old node Prev-> next to the new node, and the old node's next-> Prev to the new node.

static inline void list_replace(struct list_head *old,                struct list_head *new)                                             {    new->next = old->next;        new->next->prev = new;        new->prev = old->prev;        new->prev->next = new;    }

At this time, the next and Prev pointers of the old node still point to the original node. You can use the following function to re-initialize the old node and direct it to itself.

static inline void list_replace_init(struct list_head *old,                    struct list_head *new){    list_replace(old, new);    INIT_LIST_HEAD(old);}

...

In more general cases: we replace the linked list nodes mostly at the head or end of the linked list, so we have the following functions:

static inline void list_move(struct list_head *list, struct list_head *head)

Replace the linked list Header

static inline void list_move_tail(struct list_head *list,                  struct list_head *head)

Replace the end of the linked list

Chain table judgment

Sometimes we need to determine whether the linked list is empty or has reached the end of the linked list.

The kernel linked list has implemented these judgment functions for us.

Check whether the linked list is empty

static inline int list_empty(const struct list_head *head){    return head->next == head;}

Check whether the function has reached the end of the linked list:

static inline int list_is_last(const struct list_head *list,                const struct list_head *head)

In addition, there is a function to check whether the linked list is empty.

static inline int list_empty_careful(const struct list_head *head)

Check that the linked list is empty and no other processor is available to operate on it.

Merge two linked lists

Merging a linked list is similar to adding a linked list node. adding a new linked list at the head or end of the linked list will call _ list_splice.

static inline void __list_splice(const struct list_head *list,                 struct list_head *prev,                 struct list_head *next){    struct list_head *first = list->next;    struct list_head *last = list->prev;    first->prev = prev;    prev->next = first;    last->next = next;    next->prev = last;}

Add list linked list to Prev and next

Add a new linked list in the linked list header:

static inline void list_splice(const struct list_head *list,                struct list_head *head)

Add a new linked list call at the end of the linked list:

static inline void list_splice_tail(struct list_head *list,                struct list_head *head)

Split a linked list

static inline void list_cut_position(struct list_head *list,        struct list_head *head, struct list_head *entry)

Split a linked list with entry as the node and head as the header. After splitting, the list stores the linked list from head to entry. The head returns the chain table from entry-> next to the end of the chain table.

Traversal chain table

The purpose of creating a linked list is to obtain valid data in the linked list structure through a traversal table.

As mentioned in the previous article, list_entry can only obtain the struct corresponding to one linked list node.

We can use a for loop to traverse a table:

for (pos = head->next; pos != head; pos = pos->next){     struct data_struct *data = list_entry(pos, struct data_struct, list);     ...}

Of course, the kernel has provided us with a set of interfaces (essentially the for loop above)

list_for_each(pos, head)

Here we want a simpler one: we can use list_entry to get the data structure corresponding to the linked list node while looping. Therefore, the kernel engineer gave us an interface:

list_for_each_entry(pos, head, member)

POs: a pointer to the data structure, head is the head of the linked list, and member is the name of the linked list member in the data structure.

For example, the current definition

struct data_struct{    struct list_head list;    Data data;};

We want to obtain this structure from a traversal table.

{    ...    struct data_struct *pdata;    list_for_each_entry(pdata, head, list){         Data tmp = pdata->data;         ....    }}

In the traversal of these versions, we cannot delete nodes in the loop. How can a delete operation cause the kernel to crash (because node-> next is set to null during Node Deletion, if you perform operations .....), however, sometimes you need to delete the Node during the traversal process. Therefore, the kernel Nb engineer helped us to create a for_safe version, which saves a copy of the node. After the node is deleted, the copy remains valid.

list_for_each_safe(pos, n, head)
list_for_each_entry_safe(pos, n, head, member)

Here N is used to save the copy.

In addition, reverse traversal and so on will not be repeated again ......

Please check include/Linux/list. h on your own

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.