首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Linux 2.6内核中新的锁机制--RCU(4)RCU 典型应用3

Linux 2.6内核中新的锁机制--RCU(4)RCU 典型应用3

3.修改操作立即可见
前面两种情况,读者能够容忍修改可以在一段时间后看到,也就说读者在修改后某一时间段内,仍然看到的是原来的数据。在很多情况下,读者不能容忍看到旧的数据,这种情况下,需要使用一些新措施,如System V IPC,它在每一个链表条目中增加了一个deleted字段,标记该字段是否删除,如果删除了,就设置为真,否则设置为假,当代码在遍历链表时,核对每一个条目的deleted字段,如果为真,就认为它是不存在的。
还是以系统调用审计代码为例,如果它不能容忍旧数据,那么,读端代码应该修改为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static enum audit_state audit_filter_task(struct task_struct *tsk)
{
         struct audit_entry *e;
         enum audit_state   state;
         rcu_read_lock();
         list_for_each_entry_rcu(e, &audit_tsklist, list) {
                 if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
                         spin_lock(&e->lock);
                         if (e->deleted) {
                                 spin_unlock(&e->lock);
                                 rcu_read_unlock();
                                 return AUDIT_BUILD_CONTEXT;
                         }
                         rcu_read_unlock();
                         return state;
                 }
         }
         rcu_read_unlock();
         return AUDIT_BUILD_CONTEXT;
}




注意,对于这种情况,每一个链表条目都需要一个spinlock保护,因为删除操作将修改条目的deleted标志。此外,该函数如果搜索到条目,返回时应当保持该条目的锁,因为只有这样,才能看到新的修改的数据,否则,仍然可能看到就的数据。
写端的删除操作将变成:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static inline int audit_del_rule(struct audit_rule *rule,
                                  struct list_head *list)
{
         struct audit_entry  *e;
         /* Do not use the _rcu iterator here, since this is the only
          * deletion routine. */
         list_for_each_entry(e, list, list) {
                 if (!audit_compare_rule(rule, &e->rule)) {
                         spin_lock(&e->lock);
                         list_del_rcu(&e->list);
                         e->deleted = 1;
                         spin_unlock(&e->lock);
                         call_rcu(&e->rcu, audit_free_rule, e);
                         return 0;
                 }
         }
         return -EFAULT;         /* No matching rule */
}




删除条目时,需要标记该条目为已删除。这样读者就可以通过该标志立即得知条目是否已经删除。
六、小结RCU是2.6内核引入的新的锁机制,在绝大部分为读而只有极少部分为写的情况下,它是非常高效的,因此在路由表维护、系统调用审计、SELinux的AVC、dcache和IPC等代码部分中,使用它来取代rwlock来获得更高的性能。但是,它也有缺点,延后的删除或释放将占用一些内存,尤其是对嵌入式系统,这可能是非常昂贵的内存开销。此外,写者的开销比较大,尤其是对于那些无法容忍旧数据的情况以及不只一个写者的情况,写者需要spinlock或其他的锁机制来与其他写者同步。
在作者先前的两篇文章"Linux 实时技术与典型实现分析, 第 1 部分: 介绍"和"Linux 实时技术与典型实现分析, 第 2 部分: Ingo Molnar 的实时补丁"中,Ingo Molnar的实时实现要求RCU读端临界区可抢占,而RCU的实现的前提是读端临界区不可抢占,因此如何解决这一矛盾但同时不损害RCU的性能是RCU未来的一大挑战。
返回列表