hlist哈希链表

本文详细介绍了Linux内核中的hlist哈希链表结构。针对其独特的设计思路进行了深入剖析,包括hlist_head和hlist_node的数据结构定义,以及如何通过pprev指针实现高效的节点插入和删除操作。

近日看了下linux TCP/IP kernel方面的知识,进而研究了下hlist链表,中间有点小小的迷惑但还是在广大网友的帮助下解决了,本想写点关于这方面的知识,一方面才思不佳,另一方面网上很多关于这方面的介绍,现转载一下,希望对各位有所帮助。 ­

­

   转载:http://www.yatan.com/group/topic.php?tid=21607 ­

hlist哈希链表是内核中常用的一个数据结构,由于它不同于普通的链表,所以这里对hlist哈希链表进行一下分析,希望对大家有所帮助。 ­

  在include/Linux/list.h中有list链表与hlist哈希链表结构的定义,下面都列出它们的定义,可以对比一下: ­

struct list_head { ­

struct list_head *next, *prev; ­

}; ­

 

struct hlist_head { ­

struct hlist_node *first; ­

}; ­

 

struct hlist_node { ­

struct hlist_node *next, **pprev; ­

}; ­

    双头(next,prev)的双链表对于Hash表来说“过于浪费”,因而另行设计了一套Hash表专用的hlist数据结构——单指针表头双循环链表,hlist的表头仅有一个指向首节点的指针,而没有指向尾节点的指针,这样在可能是海量的Hash表中存储的表头就能减少一半的空间消耗。 ­

    pprev因为hlist不是一个完整的循环链表而不得不使用。在list中,表头和节点是同一个数据结构,直接用prev没问题;在hlist中,表头没有prev,也没有next,只有一个first。为了能统一地修改表头的first指针,即表头的first指针必须修改指向新插入的节点, hlist就设计了pprev。hlist节点的pprev不再是指向前一个节点的指针,而是指向前一个节点(可能是表头)中的next(对于表头则是 first)指针(struct list_head **pprev),从而在表头插入的操作可以通过一致的“*(node->pprev)”访问和修改前节点的next(或first)指针。 ­

注:pprev是指向前一个节点中的next指针,next是指向hlist_node的指针,所以pprev是一个指向hlist_node的指针的指针。 ­

图片­

    注意: ­

    pprev可以理解成向list的prev一样,是一个指向hlist_node的指针,又由于hlist_node的第一个元素next是一个指向 hlist_node的指针,pprev也是一个指向next的指针,即pprev是一个指向hlist_node的指针的指针。 ­

struct hlist_node Prev; ­

struct hlist_node *pprev = (struct hlist_node *) Prev ­

                                     = (struct hlist_node *) (struct hlist_node * next) ­

                                     = struct hlist_node ** next; ­

   下面是hlist中常用的几个宏: ­

#define HLIST_HEAD_INIT { .first = NULL } ­

#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL } ­

#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL) ­

#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL) ­

下面只列出hlist_add_before操作函数,其他hlist链表操作函数操作方法类似。这个函数中的参数next不能为空。它在next前面加入了n节点。函数的实现与list中对应函数类似。 ­

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_add_before(struct hlist_node *n,struct hlist_node *next) ­

{ ­

n->pprev = next->pprev; ­

n->next = next; ­

next->pprev = &n->next; ­

*(n->pprev) = n; ­

}

 ­

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值