Hashed hash list in Linux kernel

Source: Internet
Author: User

Describe the implementation of hash lists in the Linux kernel, which is used very much in the Linux kernel hash list.

And I later in the software design, it is also very likely to use. Hash lists are, after all, very handy in the search process for data.

The Linux kernel's implementation of hash lists is perfect, so it's very necessary to learn.


In the implementation of the hash list, two very useful structures are used:

Hash list header Structure body:

struct Hlist_head

{

struct Hlist_node *first;

}


Hash list of the node structure:

struct Hlist_node

{

struct Hlist_node *next;

struct Hlist_node **pprev;

}


The organization chart of the hash list in the kernel:
650) this.width=650; "src=" Http://s3.51cto.com/wyfs02/M00/51/93/wKioL1RjgImhklrhAAJLAdwrRpA271.jpg "title=" Hashed hash list structure in the Linux kernel. png "alt=" wkiol1rjgimhklrhaajladwrrpa271.jpg "/>


As to why the kernel does not define the head node (struct hlist_head) of the hash table as the same as the struct hlist_node.

The explanation in the kernel is that the hash list should be used in the kernel very much, the head node is defined as the struct Hlist_head {struct Hlist_node *first} can save half of the memory space.

In order to implement the same operation for all nodes in the hash list, the head node of the hash list does not need to be treated as an exception. So members of struct Hlist_node **pprev are defined in struct Hlist_node.

struct Hlist_node The role of the Pprev member in the struct: The next member of the previous struct hlist_node struct that points to the current struct Hlist_node node.


1. Definition and initialization of hash-list header nodes:

#define HLIST_HEAD (name) \

struct Hlist_head name = {. First = NULL}


2. Initialization of hash list header:

#define HLIST_HEAD_INIT (PTR) ((ptr)->first = NULL)

3. Initialization of the hash table data node:

static inline void Hlist_node_init (struct hlist_node *node)

{

Node->next = NULL;

Node->pprev = NULL;

}

4. Determine if a hash list is empty:

int hlist_empty (struct hlist_head *head)

{

Return!head->first;

}


5. Determine if a hash node is hashed in the hash list:

int Hlist_unhash (struct hlist_node *node)

{

Return!node->pprev; If Node->pprev is empty, it indicates that node is not in the hash link

}

6. Remove a node from a hash link:

void __hlist_del (struct hlist_node *node)

{

struct Hlist_node *next = node->next;

struct Hlist_node **pperv = node->pperv;


if (next)

Next->pprev = Pperv;

*pperv = Next; or * (node->pprev) = next;

}

When you delete a node element in a hash link, you need to consider whether the deleted element is the end element in the link.


7. Remove a node from a hash link and initialize it:

void __hlist_node_init (struct hlist_node *node)

{

if (!hlist_unhash (node))

__hlist_del (node)

Hlist_node_init (node);

}


8. Add a node element behind the head of the hash list:

void Hlist_add_head (struct hlist_head *head, struct hlist_node *new)

{

New->next = head->first;

New->pprev = & (Head->first);

if (!hlist_empty (head))

Head->first->pprev = & (New->next);

Head->first = new;

}

Note: Adding a node after the header in the hash link is a consideration: whether the node being joined is the first node element

9. Add a node after a node in the hash link:

void Hlist_add_after (struct hlist_node *node, struct hlist_node *new)

{

struct Hlist_node *tmp = node->next;

New->next = tmp;

New->pprev = & (Node->next);

Node->next = new;

if (TMP)

Tmp->pprev = & (New->next);

}

10. Add a node to the front of a node in the hash link:

void Hlist_add_before (struct hlist_node *node, struct hlist_node *new)

{

struct Hlist_node **tmp = node->pprev;


New->next = node;

New->pperv = node->pprev;

*tmp = new;

Node->pprev = & (New->next);

}


11. Move a hash link from one head node to another head node:

void Hlist_move_list (struct hlist_head *old, struct hlist_head *new)

{

struct Hlist_node *tmp = old->first;

New->first = tmp;

if (TMP)

Tmp->pprev = & (New->first);

Old->first = NULL;

}


To iterate over the elements in the hash list:

Iterate over each struct hlist_node{} struct body:

POS is used to store the address of each struct hlist_node structure;

Head: The header node of the hash table;

1. #define Hlist_for_each (POS, head) \

for (pos = (head)->first;  pos! = NULL; pos = pos->next)


2. #define HLIST_FOR_EACH_SAFE (POS, tmp, head) \

for (pos = (head)->first, tmp = pos->next; \

pos! = NULL; \

POS = tmp, TMP = Pos->next)


Iterate over each element in the hash list:

PTR: Is the address of struct hlist_node structure;

Member: is the member name of the struct hlist_node struct embedded in the other structure body;

Type: is the strcut structure of the hlist_node structure;

1. #define Hlist_entry (PTR, member, type) \

Container_of (PTR, type, member)

The Hlist_entry () is used to find the address of the structure embedded in the struct Hlist_node structure body;


POS: The address of a struct that is used to hold the structure embedded in the hlist_node structure;

Node: The address for storing the next struct hlist_node struct in a hash link;

Head: The header node of the hash table;

Member:struct Hlist_node a member name in a large structure;

2. #define HLIST_FOR_EACH_ENTRY (POS, node, head, member) \

for (node) = head->first; \

(node)! = NULL && pos = hlist_entry (node, member, typeof (*pos)); \

(node) = (node)->next)


Continue traversal from struct hlist_node *node node;

3. #define HLIST_FOR_EACH_ENTRY_CONTINUE (POS, node, member) \

for (node) = (node)->next; \

(node)! = NULL && pos = hlist_entry (node, member, typeof (*pos)); \

(node) = (node)->next)


Continue traversing from struct hlist_node *node;

4. #define HLIST_FOR_EACH_ENTRY_FROM (POS, node, member) \

for (; \

(node)! = NULL && pos = hlist_entry (node, member, typeof (*pos)); \

(node) = (node)->next)



The Hlist_for_each_entry_safe () function is used to delete an element while traversing the link.

POS: The address used to store elements in the link;

Node: The address used to store the struct hlist_node struct in the link;

TMP: The address of the next struct hlist_node struct in the cache link;

Head: The node of the chain header of the hash table; struct hlist_head;

The member name of the MEMBER:STRUCT hlist_node structure in the large structural body;

5. #define HLIST_FOR_EACH_ENTRY_SAFE (POS, node, TMP, head, member)

for (node) = (head)->first; \

(node)! = NULL && (tmp) = (node)->next &&

pos = hlist_entry (node, member, typeof (*pos)); \

(node) = (TMP))


These operations on hash lists, which I write based on the various operations of the hash list in the kernel, are rooted in the/include/linux/list.h file.


This article is from the "FAI Aberdeen" blog, please make sure to keep this source http://weiguozhihui.blog.51cto.com/3060615/1575925

Hashed hash list in Linux kernel

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.