Linked List of Linux kernel learning

Source: Internet
Author: User

This article is written in accordance with section 3.6 of the Linux kernel cultivation path of renqiao.

The linked list data structure is used in many parts of the Linux kernel. I believe that students of the class or those who have learned the data structure are no stranger. Good news, he is the simplest linear structure-linked list. However, in the kernel, the data structure of the cyclic double join table is generally used. I will not post the source code here because there are more than three hundred lines. If you are interested, download: http://download.csdn.net/detail/huiguixian/3889011.

1. Definition of linked list

This is just as simple as learning in textbooks. Includes a forward pointer and a back pointer. Something wrong? No data domain! Don't worry, let's take a look.

struct list_head {        struct list_head *next, *prev;};

No data is a major feature of the kernel linked list, because it adopts a special method. Instead of using a linked list to contain data, the data items are reversed to include the linked list. At the beginning, it is more or less difficult to understand. I will explain it below.

2. Definition and initialization of the linked list

(1) Static initialization during compilation using the list_head macro

#defineLIST_HEAD_INIT(name) { &(name), &(name) }#defineLIST_HEAD(name) \        struct list_head name =LIST_HEAD_INIT(name)

List_head_init is a macro definition. That is to say, it is easy to understand it by extending it. For example, the initialization statement is

List_head (event_list), which can be understood

struct list_headevent_list = { &event_list, &event_list }

You should have forgotten the struct. There is a piece in it that can be initialized in the defined order of members, so this sentence is very obvious. The purpose is to initialize the next Prev pointer to itself.

(2) The init_list_head function is used for dynamic initialization during runtime. This goal is displayed at a glance, as shown above.

static inline voidINIT_LIST_HEAD(struct list_head *list){        list->next = list;        list->prev = list;}

3. To determine whether the linked list is empty is to determine whether it points to itself.

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

4. insert operations. If you have learned how to operate the linked list, you can learn the linked list.

static inline void__list_add(struct list_head *new,                             struct list_head *prev,                             struct list_head *next){        next->prev = new;        new->next = next;        new->prev = prev;        prev->next = new;}static inline voidlist_add(struct list_head *new, struct list_head *head){        __list_add(new, head,head->next);}static inline voidlist_add_tail(struct list_head *new, struct list_head *head){        __list_add(new, head->prev,head);}

5. Move, delete, and so on, mainly for traversal! The wonderful part of traversal is that the linked list is contained by data packets. How to retrieve the data that contains the data through the contained linked list (a bit of mouth)

For example, the example in the book:

struct list_head*tmp;struct usb_hub *hub;tmp =hub_event_list.next;hub = list_entry(tmp,struct usb_hub, event_list);

The data structure is usb_hub, which contains a list_head data item, and now there is a list_head linked list hub_event_list. You need to retrieve the data usb_hub containing hub_event_list.next. This is the function of the above Code. The most important function is list_entry. The Code is as follows:

#definelist_entry(ptr, type, member) \        container_of(ptr, type, member)

This does not need to be explained. He calls container_of (PTR, type, member) and looks at this macro definition directly.

#definecontainer_of(ptr, type, member) ({         \    const typeof( ((type *)0)->member )*__mptr = (ptr);    \    (type*)( (char *)__mptr - offsetof(type,member) );})#defineoffsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)

This looks laborious. Step by step. First, macro definition is not a function, and macro-defined parameters are not restricted by the function. Therefore, the second parameter in list_entry and container_of is made of data type parameters. In addition, GCC has an extension to iso c, that is, it supports the typeof operation, you can see here: http://blog.csdn.net/huiguixian/article/details/7045311. Let's take a look at the description of typeof. Simply put, it can return a type, which can be used at any time you want to use.

The above example is explained as follows:

Type is usb_hub, type * Is usb_hub *, 0 can be understood as null, that is, usb_hub-> event_list is (type *) 0)-> member. The entire sentence defines a constant pointer of the list_head type, pointing to the event_list parameter. Then, the next step is to calculate the offset so that the pointer is subtracted from the offset, that is, the pointer pointing to the offset can be viewed as a data structure of usb_hub, and then the usb_hub is taken out.

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.