Linux內核數據結構hlist_head


參考自:https://blog.csdn.net/zhanglei4214/article/details/6767288

一、hlist結構簡介

hlist_head 和 hlist_node 是位於linux內核中的數據結構,其設計初衷主要是為了減少Hash表的內存消耗。

struct hlist_head {
  struct hlist_node *first;
};

struct hlist_node {
  struct hlist_node *next, **pprev;
};

其內存結構如下:

 

 

hlist_head 結構體僅僅有一個first指針.

hlist_node 結構體有兩個指針,next 和 ppre。其中next指針指向下一個hlist_node,如果該節點為最后一個一個節點,那么next指向NULL。

這樣設計的原因在於:通常我們在使用Hash表是為實現快速查找,那么Hash表通常會維護一張相對較大的數組,否則的會帶來較大的沖突,而一張較大的數組必然會帶來較大的內存消耗。我們知道通常一個Hash表中每一個dentry(每一個具體數元素)會使用兩個指針,有其中一個指向尾節點,而我們知道在Hash表中的list通常是非常短(如果過長,說明沖突過多),那么顯然這個指向尾節點的指向我們就不那么的必要,Hash表中的每一個denry只用保存一個指針。這樣的設計顯然會造成鏈表中節點數據結構不一致,如果hlist_node采用的next和pre指針,那么對於第一個節點和其他節點操作必然會使不一致。hlist_node巧妙地將pprev指向上一個節點的next指針的地址,由於hlist_head和hlist_node指向的下一個節點的指針類型相同,這樣就解決了通用性。

二、常用接口

(1)hlist_head 和 hlist_node初始化

#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
static inline void INIT_HLIST_NODE(struct hlist_node *h) 
{
  h->next = NULL;
  h->pprev = NULL;
}

(2)添加節點

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;
}

(3)刪除節點

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_POISON1;
  n->pprev = LIST_POISON2;
}

(4)遍歷節點

#define hlist_for_each_entry(pos, head, member)       \
  for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
       pos;             \
       pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM