当前位置:   article > 正文

Linux中通用链表(list)的解析(2)_config_debug_list

config_debug_list
1. 下面介绍list的插入函数:
#ifndef CONFIG_DEBUG_LIST
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;
}
#else
extern void __list_add(struct list_head *new,
                  struct list_head *prev,
                  struct list_head *next);
#endif
这个函数的3个参数分别是:
new: 要插入的结点;
prev: 插入之后new的前一个结点;
next: 插入之后new的后一个结点.

下面接着的是:
#ifndef CONFIG_DEBUG_LIST
static inline void list_add(struct list_head *new, struct list_head *head)
{
    __list_add(new, head, head->next);
}
#else
extern void list_add(struct list_head *new, struct list_head *head);
#endif
这是将上面的3参函数改为2参函数的调用, 表示把new插入到head后面.

同理:
static inline void list_add_tail(struct list_head *new, struct list_head *head)
{
    __list_add(new, head->prev, head);
}
这表示把new插入到head前面.

接下来的:
static inline void __list_add_rcu(struct list_head * new,
        struct list_head * prev, struct list_head * next)
{
    new->next = next;
    new->prev = prev;
    smp_wmb();
    next->prev = new;
    prev->next = new;
}
引领的是几个rcu protected的插入函数.


2. 下面介绍list的删除函数:
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
    next->prev = prev;
    prev->next = next;
}
通过要删除结点的前后两结点作为参数,使它们互相指向.
static inline void list_del_init(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    INIT_LIST_HEAD(entry);
}
删除entry结点, 并把它的prev和next值指向安全区(即自己).

#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
    __list_del(entry->prev, entry->next);
    entry->next = LIST_POISON1;
    entry->prev = LIST_POISON2;
}
#else
extern void list_del(struct list_head *entry);
#endif
通过调用上面的__list_del函数实现删除结点, 并且指定entry结点prev,next指针的值.
两个宏在linux/poison.h中定义如下:
/********** include/linux/list.h **********/
/*
 * These are non-NULL pointers that will result in page faults
 * under normal circumstances, used to verify that nobody uses
 * non-initialized list entries.
 */
#define LIST_POISON1  ((void *) 0x00100100)
#define LIST_POISON2  ((void *) 0x00200200)
细心的人可能发现了, 结点在被从list中删除后并没有释放, 这是因为在创建和插入结点的时候也没有申请资源, 在C/C++中的原则是哪里申请哪里释放.
rcu_del的函数同rcu_add, 不再说明.

3. 下面介绍list的替换函数:
static inline void list_replace(struct list_head *old,
                struct list_head *new)
{
    new->next = old->next;
    new->next->prev = new;
    new->prev = old->prev;
    new->prev->next = new;
}
这个函数用new结点替换list中的old结点.
static inline void INIT_LIST_HEAD(struct list_head *list)
{
    list->next = list;
    list->prev = list;
}
这个函数把参数中的list结点的prev和next指向自己.
static inline void list_replace_init(struct list_head *old,
                    struct list_head *new)
{
    list_replace(old, new);
    INIT_LIST_HEAD(old);
}
这个函数是综合上面两个函数, 在用new替换old之后, 使old结点的prev和next指向安全区(即自己).
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/128125
推荐阅读
相关标签
  

闽ICP备14008679号