加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 运营中心 > 交互 > 正文

深入理解RCU实现

发布时间:2016-10-29 16:06:37 所属栏目:交互 来源:站长网
导读:副标题#e# 深入理解RCU实现 ——基于 内核2.6.21 RCU实现(lvyilong316) RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。对于被RCU保护的共享数据结构, 读者不需要获得任何锁就可以访问它,但写者在访问它时首先拷贝一个副本,然

RCU链表操作

为了操作链表,在include/linux/rculist.h有一套专门的RCU API。如:list_entry_rcu、list_add_rcu、list_del_rcu、list_for_each_entry_rcu等。即对所有kernel 的list的操作都有一个对应的RCU操作。那么这些操作和原始的list操作有哪些不同呢?我们先对比几个看下。

list_entry_rcu

#define list_entry_rcu(ptr, type, member)

container_of(rcu_dereference(ptr), type, member)

#define list_entry(ptr, type, member)

container_of(ptr, type, member)

__list_for_each_rcu

#define __list_for_each_rcu(pos, head)

for (pos = rcu_dereference((head)->next);

pos != (head);

pos = rcu_dereference(pos->next))

#define __list_for_each(pos, head)

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

从__list_for_each_rcu和list_entry_rcu的实现可以看出,其将指针的获取替换为使用rcu_dereference。

list_replace_rcu

static inline void list_replace_rcu(struct list_head *old,

struct list_head *new)

{

new->next = old->next;

new->prev = old->prev;

rcu_assign_pointer(new->prev->next, new);

new->next->prev = new;

old->prev = LIST_POISON2;

}

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;

}

    从list_replace_rcu的实现可以看出,RCU API的实现将指针的赋值替换为rcu_assign_pointer。

list_del_rcu

static inline void list_del_rcu(struct list_head *entry)

{

__list_del(entry->prev, entry->next);

entry->prev = LIST_POISON2;

}

static inline void list_del(struct list_head *entry)

{

__list_del(entry->prev, entry->next);

entry->next = LIST_POISON1;

entry->prev = LIST_POISON2;

}

从list_del_rcu的实现,可以看出RCU API的实现没有将删除项的next指针置为无效。这样实现是为了防止删除节点时,读者还在遍历该节点。

RCU链表API使用

下面看下RCU list API的几个应用示例。

只有增加和删除的链表操作

    在这种应用情况下,绝大部分是对链表的遍历,即读操作,而很少出现的写操作只有增加或删除链表项,并没有对链表项的修改操作,这种情况使用RCU非常容易,从rwlock转换成RCU非常自然。路由表的维护就是这种情况的典型应用,对路由表的操作,绝大部分是路由表查询,而对路由表的写操作也仅仅是增加或删除,因此使用RCU替换原来的rwlock顺理成章。系统调用审计也是这样的情况。

    这是一段使用rwlock的系统调用审计部分的读端代码:

       static enum audit_state audit_filter_task(struct task_struct *tsk)

        {

                struct audit_entry *e;

                enum audit_state   state;

                read_lock(&auditsc_lock);

                /* Note: audit_netlink_sem held by caller. */

                list_for_each_entry(e, &audit_tsklist, list) {

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读