Linux Kernel list Depth Analysis __linux

Source: Internet
Author: User
Tags prev

Introduction to the linked list:

A linked list is a commonly used data structure that connects a series of data nodes into a data chain through pointers. Relative to the array, the linked list has a better dynamic, the establishment of the linked list without prior knowledge of the total amount of data, you can randomly allocate space, you can efficiently in the linked list of any location in real-time insertion or deletion of data. The cost of the linked list is mainly the order of access and the space loss of the organization chain.

The core list of good mainly embodies two points, 1 is extensible, 2 is encapsulation. Scalability is certainly necessary, the kernel has been in development, so the code can not write dead code, to facilitate modification and append. The common operation of the linked list is encapsulated, the user only focus on the interface, do not need to focus on implementation. Analyze the linked list in the kernel what can we do about it? I think it can be reused to user state programming, later in the user state programming will not need to write some about the list of code, directly in the kernel of the list.h in the code copy over. You can also sort out the my_list.h and include it directly into the C file in later user state programming.

1. Linked list comparison

Traditional linked list and kernel linked list

Traditional linked list: Generally refers to one-way linked list

struct List

{

struct List *next;//link table node pointer field

};

Kernel chain list: bidirectional cyclic link list design is designed to design a universal unified two-way list.

struct List_head

{

struct List_head *head, *prev;

};

The List_head structure contains two pointers to the list_head structure body

Prev and Next, this shows that the kernel's linked list has a double linked list function, in fact, it is usually organized into a two-way circular chain list

2. Kernel Linked list use

1. Init_list_head: Create a linked list

2. List_add: Insert node in the header of the linked table

3. List_add_tail: Inserts a node at the end of the list

4. List_del: Delete node

5. List_entry: Remove the node

6. List_for_each: Traversing the list

(If we do not know the parameters of these functions and the internal implementation of the function, learn to check the parameters of these functions or implement the code the best way to directly view the kernel source, knot and the previous use of the Sourceinsight tool directly search the names of these functions)



Here's an example: Check the Init_list_head function,


This is to first the kernel source code into the Sourceinsight project inside. Source code can be downloaded on the official web, and then unzipped under Linux (FileName Linux case, Windows is not case-sensitive), and then through Samba and mapped network drive features (mentioned in front of Sourceinsight Bowen), Click on the icon on the left side of the R icon (like an open book)


This allows you to quickly see the Code Implementation section: In the kernel mkregtale.c file

 * * This is a simple doubly linked list implementation that matches the
 * way the Linux kernel doubly linked list Implementation works.
 * *

struct List_head {
	struct list_head *next;/* Next in Chain * * struct list_head *prev
	;/* Previous in Chain */
};

This list, which contains no data fields, can be embedded in any data structure, such as defining a list of data fields as follows:

struct score
{
	int num;
	int 中文版;
	int math;
	struct List_head list;//chain link links field
};

struct List_head score_head;//Linked list header
Init_list_head (&score_head)//Init chain header completes the creation of a two-way cyclic linked list
The red section above initializes an existing List_head object, score_head as a pointer to a struct, so that the stack and the Score_head object defined by the global zone can be initialized. By calling the Init_list_head () macro to initialize the linked list node and pointing both the next and the prev pointers to itself, we construct an empty double loop list.

Initialize an empty list: In fact, it is the header of a linked table, which points to the first node. Defines the node and initializes it. And then the two-way cyclic list is born.

Static is added to the function, which means that the function is a static function, which is actually a restriction on the scope, meaning that the function scope is limited to this file. Therefore, static has the role of information concealment. The function of the inline keyword, called an inline function, indicates that the compiler immediately expands the function when it calls the function.

/* Initialise A list head to a empty list *
/static inline void Init_list_head (struct list_head *list)
{
        list ->next = list;
	List->prev = list;
}

List_add: Inserting nodes in the header of a linked table

/**
* List_add-add A new entry
* @new: New entry to is added
* @head: List head to add it after
*
   * Insert A new entry after the specified head.
* This is good a for implementing stacks.
*
/static inline void List_add (struct list_head *new, struct list_head *head)
{
  __list_add (new, head, Head->next);
}

 * * Insert A new entry between two known consecutive entries.
 * * This is a for
 internal list manipulation where we know
 * The Prev/next entries
 already! * *
#ifndef config_debug_list
static inline void __list_add (struct list_head *new,
			      struct List_head *prev,< C8/>struct list_head *next)
{
	next->prev = new;
	New->next = Next;
	New->prev = prev;
	Prev->next = new;
}
#else
extern void __list_add (struct list_head *new,
			      struct list_head *prev,
			      struct list_head);
#endif


List_add_tail: Inserting a node at the end of a list

/**
* List_add_tail-add A new entry
* @new: New entry to is added
* @head: List head to add it before
  
    * *
Insert A new entry before the specified head.
* This is useful for implementing queues.
*
/static inline void List_add_tail (struct list_head *new, struct list_head *head)
{
    __list_add (new, head-& Gt;prev, head);



  

Usage examples:

struct SCORE
{
int num;
int 中文版;
int math;
struct List_head list;//chain table Access field
};

struct List_head score_head;//Linked list header
Define three nodes and insert them into the list
struct score stu1, STU2, STU3;

List_add_tail (& (Stu1.list), &score_head)//using the trailing interpolation method

Each dual-cycle list of Linux has a chain header, and the header is also a node, but it is not embedded in the host data structure, that is, the linked table header can not be used to locate the corresponding host structure, but the virtual host structure pointers are obtained.


List_del: Deleting nodes

/* Take an element out of it current list, with or without
 * reinitialising the links.of entry*/
static Inlin e void List_del (struct list_head *entry) {struct List_head *list_next
	= entry->next;
	struct List_head *list_prev = entry->prev;

	List_next->prev = List_prev;
	List_prev->next = List_next;

}



List_entry: Remove Node

/**
* List_entry-get The struct for this entry
* @ptr: The &struct list_head.
* @type: the Ty PE of the struct this are embedded in.
* @member: The name of the list_struct within the struct.
*/
#define LIST_ENTRY (PTR, type, member) \
    container_of (PTR, type, member)


/**
 * Container_of-cast A member of a structure out to the containing structure
 * @ptr: The pointer to the    m Ember.
 * @type: 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);})



List_for_each: Traversing the list

#define List_for_each (POS, head)
    /for (pos = (head)->next; prefetch (pos->next), Pos!= (head); \
    pos = PO S->next) </span></span>

As you can see, using the secondary pointer Pos,pos starts with the first node and does not have access to the head node until the POS reaches the head node pointer. And this traversal is just to find the current position of a node, how to get the address of the starting node through the POS, so you can reference the domain of the node. List_entry macros are defined in List.h: #define List_entry (PTR, type, member) \ (type *) ((char *) (PTR )-(unsigned Long) (& ((type *) 0)-> member)) Analysis: (unsigned Long) (& (Type *) 0)-> m Ember) converts the 0 address into a pointer to the type structure, and then gets a pointer to the member field in the struct, which is the offset of member in the type structure. WHERE (char *) (PTR) is to find the absolute address of PTR, the two subtract, and then get the type of the structure of the start address, that is, the address of the starting node. The use of the method is very ingenious. For example, the following usage:

struct score stu1, STU2, STU3;
struct List_head *pos;//defines a node pointer.
struct score *tmp;//defines a score structure variable

Traverse the entire list, each traversal will print out the data
	List_for_each (POS, &score_head)//POS will automatically be assigned a new value
	{
		tmp = list_entry (pos, struct Score, list);
		PRINTK (kern_warning "num:%d, 中文版:%d, Math:%d\n", Tmp->num, Tmp->english, Tmp->math);
	



List_for_each_safe: The release of a linked list

/**
* list_for_each_safe-iterate over a list safe against removal of list entry
* @pos: the &struct list_he Ad to use as a loop cursor.
* @n:another &struct List_head to use as temporary storage
* @head: </span>the head for your list.
*/
   #define LIST_FOR_EACH_SAFE (POS, N, head)/For
    (pos = (head)->next, n = pos->next; pos!= (head); \
        PO s = N, n = pos->next)


3. Kernel Chain List Realization analysis


4. Porting the kernel list (here is a small routine of kernel module with kernel list)

MYLIST.C file

#include <linux/module.h> #include <linux/init.h> #include <linux/list.h>//contains kernel-linked header files struct score {
	int num;
	int 中文版;
	int math;

struct List_head list;//chain link links field};
struct List_head score_head;//set up the linked list header//definition three nodes and then insert into the list struct score stu1, STU2, STU3; struct List_head *pos;//defines a node pointer struct score *tmp;//defines a score struct variable int mylist_init () {Init_list_head (&score_head)
	;//Initialization chain header completes the creation of a bidirectional cyclic list stu1.num = 1; Stu1.
	中文版 = 59;
	
	Stu1.math = 99;
	The three nodes are then inserted into the list List_add_tail (& (Stu1.list), &score_head);//using the trailing interpolation method stu2.num = 2; Stu2.
	中文版 = 69;
	Stu2.math = 98;
	
	List_add_tail (& (Stu2.list), &score_head);
	Stu3.num = 3; Stu3.
	中文版 = 89;
	Stu3.math = 97;
	
	List_add_tail (& (Stu3.list), &score_head);
		Traverse the entire list, each traversal will print out the data List_for_each (POS, &score_head)//POS will automatically be assigned a new value {tmp = List_entry (pos, struct score, list);
	PRINTK (kern_warning "num:%d, 中文版:%d, Math:%d\n", Tmp->num, Tmp->english, Tmp->math); } return 0;
	} void Mylist_exit () {//Exit node List_del (& (Stu1.list));
	List_del (& (Stu2.list));
PRINTK (kern_warning "MyList exit!\n");
} module_init (Mylist_init); Module_exit (Mylist_exit);

Makefile file

Obj-m: = MYLIST.O

Kdir: =/home/kernel/linux-ok6410 all

:
	make-c $ (kdir) m=$ (PWD) modules cross_compile= Arm-linux-arch=arm clean
	
:
	rm-f *.o *.ko *.order *.symvers



To load the running kernel module on the terminal:


There will be a mistake when rmmod here. But no big deal. Baidu has a lot of solutions.


Related Article

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.