zoukankan      html  css  js  c++  java
  • linux中的hlist分析应用

    在Linux中,链表有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表中存储的表头就能减少一半的空间消耗。

    最终的链表形态如下所示

    ps:1)此时与可以看到,最后一个节点的next域为空,不是循环双链表了。

         2)该图有问题,第一个节点的pprev域一个指向hlist_head->first的地址。

    由于设计了这种结构,所以其双向链表的prev域设计也做了相应的改变,在如下文章内核数据结构:hlist_head解释了为何要这样做的原因。

    static inline void __hlist_del(struct hlist_node *n)
    {
      struct hlist_node *next = n->next;
      struct hlist_node **pprev = n->pprev;

      /*这里修改的其实是它的前一节点的next值。无论该节点是不是头节点*/ <<<<1
      *pprev = next;
      /*这里修改它的后节点的pprev值,比较好理解。*/
      if (next)
        next
    ->pprev = pprev;
    }


    如果hlist_node中使用的是单级指针,那么在1处就需要判断节点是否为头节点。可以用n->prev是否被赋值,即是否为NULL来区分头结点和普通节点。在add和delete时都很容易保证头节点的prev为NULL。
    比如这样判断:

    struct my_hlist_node *next = n->next ;
    struct my_hlist_node *prev = n->prev ;
    if(n->prev)
      n
    ->prev->next = next ;
    else
      n
    ->prev = NULL ;
    if(next)    
      next
    ->prev = prev ;

    pprev有一个作用,在hlist_unhashed()中有体现。

    static inline int hlist_unhashed(const struct hlist_node *h)
    {
    return !h->pprev; /*是否为NULL,被用来判断节点是否加入到hash list中。*/
    }


    下面是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)

    常用接口

    static inline void hlist_add_before(struct hlist_node *n,struct hlist_node *next);
    static inline void hlist_add_after(struct hlist_node *n,struct hlist_node *next);
    static inline void hlist_del(struct hlist_node *entry);
  • 相关阅读:
    第三话-单一职责原则
    2014辽宁省赛 Repeat Number
    【iOS】Swift字符串截取方法的改进
    Android中特殊图形的生成样例
    Tiny server:小型Web服务器
    C语言复合字面量的使用
    浅析数据库连接池(一)
    答复学习汇编不顺利的准大学生
    Struts2拦截器
    7.数据本地化CCString,CCArray,CCDictionary,tinyxml2,写入UserDefault.xml文件,操作xml,解析xml
  • 原文地址:https://www.cnblogs.com/westfly/p/hlist_linux.html
Copyright © 2011-2022 走看看