Use Linux kernel linked list, hlist macro definition and operation in user space programming

Source: Internet
Author: User
Tags prefetch
Use the Linux kernel linked list, hlist macro definition, and operations in user space programming.

List_head and hlist_head/hlist_node in Linux kernel are two important linked list construction tools that concatenate data structures into linked lists. Using their corresponding macro definition, you can easily construct data into a linked list for various operations and data queries on the linked list.

They are widely used in the kernel. These linked list operation macro definitions are universal and irrelevant to the specific data structure.

With them, programmers do not have to operate the linked list pointer on their own, but focus on the data itself. The program using these tools is highly efficient.

Because they are the data structures defined by the kernel, it is very simple to use in kernel programming.

Struct list_head {struct list_head * Prev, * Next;} has two pointer sizes. The 32-bit system is 8 bytes.
Struct hlist_node also contains 8 bytes of 2 pointers.
Struct hlist_head occupies 4 bytes.

When they concatenate multiple identical data structures, their definitions must be added to the data structure. A single data structure can also be chained to multiple identical linked lists or different linked lists at the same time to be chained to multiple different strings.

If you do not program in the user space without the kernel, you can also use these linked lists. (In fact, most other data structures in the kernel can be used in user space ).

To "migrate to user space", you must search for the definition linked list data and macro inclusion files, copy the files, make appropriate changes, and remove the kernel-specific definition switch. If the file references other key data definitions in the kernel including the file, it is best to remove the reference and copy the definition.

The example below is an example of concatenating user data struct st with different list_head and HASH lists.
I _list is a string of a common list.
I _hash is a hash list string (actually multiple strings are scattered in the array by hash, And the hash keyword is the array subscript)

As you can imagine, the data structure is the same type of scattered containers in a freight yard. to link them together, you must install holes in the boxes with iron rings, then wire these wires can be mounted to the iron ring to concatenate them.
The definition of struct list_head in the data structure is equivalent to an iron ring and can be welded to any location of the box. The middle and tail of the header can be used.

In this example, two rings are installed on a box, and one is I _list. The box is worn with a long wire.

An I _hash ring is also installed, which is used to group boxes into different strings (each string uses an independent wire, and of course the length of each wire is short ). The heads of each wire of different strings are arranged in an array of hlist_head.

To search for a box, you can search for the long wire (traverse) and compare it one by one to find the box. But this is slow.
You can also search for a short wire directly. If you can determine in advance that the box to be searched must be in the wire string at this end-this can be done, and the role of hash.

Struct hlist_head uses only one pointer, which occupies 4 bytes, because the hash array is usually quite large, and each string is short in length (hash purpose ). This saves 4 bytes of Space multiplied by the data size.

The file list. H is an adapted version of the include/Linux/list. h file.
I will not describe the specific definition here. You can search for it by yourself. There are many explanations for kernel data structure analysis.

We recommend that you use list_head if linked list is involved in C programming! This greatly reduces your workload and time.
There are still many things in the Linux kernel that define general purpose, which are wonderful and efficient. Many can be transplanted to user programs for use.

# Include <stdio. h>
# Include <stdlib. h>
# Include "list. H"

Struct st {
Unsigned char ch;
Int this_data;

Struct list_head I _list;

Int more_data;

Struct hlist_node I _hash;

Char str_data [32];
//.......
Int end_data;
} * St;

Struct list_head list1;
Struct hlist_head hlist [1024];

# Define list size 1024

Unsigned int gethash (int c)
{
Return (C & 0xff );
}

Main ()
{
Int I;
Unsigned int hash;
Struct list_head * List;
Struct list_head * n, * P;
Struct st * PST;
Struct hlist_node * HP;

Init_list_head (& list1 );
For (hash = 0; hash <listsize; hash ++)
Init_hlist_head (& hlist [hash]);

For (I = 0; I <listsize; I ++ ){
Struct st * P = malloc (sizeof (* p ));
If (! P ){
Printf ("malloc./N ");
Break;
}

P-> CH = 'A' + I;

// String-in-length string
List_add (& P-> I _list, & list1 );


// String into the hash short string
Hash = gethash (p-> CH );
Printf ("alloc % x % d % P % u/N", p-> CH, I, P, hash );
Hlist_add_head (& P-> I _hash, & hlist [hash]);

}


// Traverse through long wire
I = 0;
List_for_each (list, & list1 ){
Struct st * P = list_entry (list, struct St, I _list );
Printf ("% P value % d = % C/N", P, I, P-> CH );
I ++;
}
Printf ("Total % d/N", I );

//----------------------
// Search for the 'C' box through the hash string
Hash = gethash ('C ');
Hlist_for_each (HP, & hlist [hash]) {
Struct st * P = hlist_entry (HP, struct St, I _hash );
Printf ("hlist: % C/N", p-> CH );

}

}

The adapted header file list. h In the user space

# Ifndef _ linux_list_h
# DEFINE _ linux_list_h

# Define offsetof (type, member) (size_t) & (type *) 0)-> Member)

# Define container_of (PTR, type, member )({/
Const typeof (type *) 0)-> member) * _ mptr = (PTR );/
(Type *) (char *) _ mptr-offsetof (type, member ));})

Static inline void prefetch (const void * X ){;}
Static inline void prefetchw (const void * X ){;}

# Define list_poison1 (void *) 0x00100100)
# Define list_poison2 (void *) 0x00200200)

Struct list_head {
Struct list_head * Next, * Prev;
};

# Define list_head_init (name) {& (name), & (name )}

# Define list_head (name )/
Struct list_head name = list_head_init (name)

# Define init_list_head (PTR) do {/
(PTR)-> next = (PTR); (PTR)-> Prev = (PTR );/
} While (0)

/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* The Prev/next entries already!
*/
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;
}

/**
* 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.
*/
Static inline void list_add (struct list_head * New, struct list_head * head)
{
_ List_add (new, head, head-> next );
}

/**
* List_add_tail-Add a new entry
* @ New: New entry to be 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-> Prev, head );
}

Static inline void _ list_del (struct list_head * Prev, struct list_head * Next)
{
Next-> Prev = Prev;
Prev-> next = next;
}

Static inline void list_del (struct list_head * entry)
{
_ List_del (Entry-> Prev, entry-> next );
Entry-> next = list_python1;
Entry-> Prev = list_python2;
}

Static inline void list_del_init (struct list_head * entry)
{
_ List_del (Entry-> Prev, entry-> next );
Init_list_head (entry );
}

Static inline void list_move (struct list_head * List, struct list_head * head)
{
_ List_del (list-> Prev, list-> next );
List_add (list, head );
}

Static inline void list_move_tail (struct list_head * List,
Struct list_head * head)
{
_ List_del (list-> Prev, list-> next );
List_add_tail (list, head );
}

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

Static inline int list_empty_careful (const struct list_head * head)
{
Struct list_head * Next = head-> next;
Return (next = head) & (next = head-> PREV );
}

Static inline void _ list_splice (struct list_head * List,
Struct list_head * head)
{
Struct list_head * First = List-> next;
Struct list_head * Last = List-> Prev;
Struct list_head * at = head-> next;

First-> Prev = head;
Head-> next = first;

Last-> next =;
At-> Prev = last;
}

/**
* List_splice-join two lists
* @ List: the new list to add.
* @ Head: the place to add it in the first list.
*/
Static inline void list_splice (struct list_head * List, struct list_head * head)
{
If (! List_empty (list ))
_ List_splice (list, head );
}

/**
* List_splice_init-join two lists and reinitialise the emptied list.
* @ List: the new list to add.
* @ Head: the place to add it in the first list.
*
* The list at @ list is reinitialised
*/
Static inline void list_splice_init (struct list_head * List,
Struct list_head * head)
{
If (! List_empty (list )){
_ List_splice (list, head );
Init_list_head (list );
}
}

# Define list_entry (PTR, type, member) container_of (PTR, type, member)

# Define list_for_each (Pos, head )/
For (Pos = (head)-> next; prefetch (POS-> next), pos! = (Head );/
Pos = pos-> next)

# DEFINE _ list_for_each (Pos, head )/
For (Pos = (head)-> next; pos! = (Head); Pos = pos-> next)

# Define list_for_each_prev (Pos, head )/
For (Pos = (head)-> Prev; prefetch (POS-> PREV), pos! = (Head );/
Pos = pos-> PREV)

# Define list_for_each_safe (Pos, N, head )/
For (Pos = (head)-> next, n = pos-> next; pos! = (Head );/
Pos = n, n = pos-> next)

# 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_for_each_entry_reverse (Pos, Head, member )/
For (Pos = list_entry (head)-> Prev, typeof (* POS), member );/
Prefetch (POS-> member. Prev), & Pos-> member! = (Head );/
Pos = list_entry (POS-> member. Prev, typeof (* POS), member ))

# Define list_prepare_entry (Pos, Head, member )/
(POS )? : List_entry (Head, typeof (* POS), member ))

# Define list_for_each_entry_continue (Pos, Head, member )/
For (Pos = list_entry (POS-> member. Next, typeof (* POS), member );/
Prefetch (POS-> member. Next), & Pos-> member! = (Head );/
Pos = list_entry (POS-> member. Next, typeof (* POS), member ))

# 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 ))

// Hash list
Struct hlist_head {
Struct hlist_node * first;
};

Struct hlist_node {
Struct hlist_node * Next, ** pprev;
};

# Define hlist_head_init {. First = NULL}
# Define hlist_head (name) struct hlist_head name = {. First = NULL}
# Define init_hlist_head (PTR)-> first = NULL)
# Define init_hlist_node (PTR)-> next = NULL, (PTR)-> pprev = NULL)

Static inline int hlist_unhashed (const struct hlist_node * H)
{
Return! H-> pprev;
}

Static inline int hlist_empty (const struct hlist_head * H)
{
Return! H-> first;
}

Static inline void _ hlist_del (struct hlist_node * n)
{
Struct hlist_node * Next = N-> next;
Struct hlist_node ** pprev = N-> pprev;
* Pprev = next;
If (next)
Next-> pprev = pprev;
}

Static inline void hlist_del (struct hlist_node * n)
{
_ Hlist_del (N );
N-> next = list_python1;
N-> pprev = list_python2;
}

Static inline void hlist_del_init (struct hlist_node * n)
{
If (n-> pprev ){
_ Hlist_del (N );
Init_hlist_node (N );
}
}

Static inline void hlist_add_head (struct hlist_node * n, struct hlist_head * H)
{
Struct hlist_node * First = H-> first;
N-> next = first;
If (first)
First-> pprev = & N-> next;
H-> first = N;
N-> pprev = & H-> first;
}

/* Next must be! = NULL */
Static inline void hlist_add_before (struct hlist_node * n,
Struct hlist_node * Next)
{
N-> pprev = Next-> pprev;
N-> next = next;
Next-> pprev = & N-> next;
* (N-> pprev) = N;
}

Static inline void hlist_add_after (struct hlist_node * n,
Struct hlist_node * Next)
{
Next-> next = N-> next;
N-> next = next;
Next-> pprev = & N-> next;

If (next-> next)
Next-> next-> pprev = & next-> next;
}

# Define hlist_entry (PTR, type, member) container_of (PTR, type, member)

# Define hlist_for_each (Pos, head )/
For (Pos = (head)-> first; POS & ({prefetch (POS-> next); 1 ;});/
Pos = pos-> next)

# Define hlist_for_each_safe (Pos, N, head )/
For (Pos = (head)-> first; POS & ({n = pos-> next; 1 ;});/
Pos = N)

# Define hlist_for_each_entry (TPOs, POs, Head, member )/
For (Pos = (head)-> first ;/
Pos & ({prefetch (POS-> next); 1 ;})&&/
({TPOs = hlist_entry (Pos, typeof (* TPOs), member); 1 ;});/
Pos = pos-> next)

# Define hlist_for_each_entry_continue (TPOs, POs, member )/
For (Pos = (POS)-> next ;/
Pos & ({prefetch (POS-> next); 1 ;})&&/
({TPOs = hlist_entry (Pos, typeof (* TPOs), member); 1 ;});/
Pos = pos-> next)

# Define hlist_for_each_entry_from (TPOs, POs, member )/
For (; POS & ({prefetch (POS-> next); 1 ;})&&/
({TPOs = hlist_entry (Pos, typeof (* TPOs), member); 1 ;});/
Pos = pos-> next)

# Define hlist_for_each_entry_safe (TPOs, POs, N, Head, member )/
For (Pos = (head)-> first ;/
Pos & ({n = pos-> next; 1 ;})&&/
({TPOs = hlist_entry (Pos, typeof (* TPOs), member); 1 ;});/
Pos = N)

# Endif

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.