免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 5716 | 回复: 13
打印 上一主题 下一主题

请教关于rcu理解的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-06-01 14:25 |只看该作者 |倒序浏览
RCU 通过保存对象的多个副本来保障读操作的连续性----但rcu rcu_read_lock()并没有指定它保护的是哪个变量啊?
它如何与call_rcu()互动,实现对数据的保护的?

ps:光看rcu_read_lock()感觉有些像保护代码区了,呵呵

论坛徽章:
0
2 [报告]
发表于 2010-06-01 15:19 |只看该作者
看 RCU 锁保护的代码时非常晕,就像你说的,在调用锁时并没有明确保护对象
只有在需要写时,临时同步数据,此时才显性知道保护的是什么

内核代码中调用 RCU 锁时经常可以看到注释,表明已在 XXX 位置得到了保护等等

论坛徽章:
0
3 [报告]
发表于 2010-06-01 15:46 |只看该作者
在我的理解中RCU更类似于一个全局的状态标志设定。

他所影响的主要是call_rcu,也就是保证call_rcu设定的函数在全部的rcu_read_lock()被unlock()之后才被执行。

论坛徽章:
0
4 [报告]
发表于 2010-06-02 10:11 |只看该作者
呵呵,ShadowStar总结的好!
想想,“类似于一个全局的状态标志”,这样更易理解!
call_rcu的时候,检查是否有在临界区的,没有就可以执行;有则等待。-----------非常概略的理解

但往深里想,似乎又有问题,应该是自己没有想透彻的缘故吧。
比如:
1)关闭了抢占的内核,rcu_read_lock()是空的,也就是说根本没有一个全局的标志存在,那么call_rcu()是如何判断执行时机的呢--------------根据call_rcu()后的上下文的切换吗?
2)假如是多核系统,是否存在这样一种情况呢: 一个cpu上在协议栈进入rcu_read_lock(),而另一个cpu上在另外一个与之相差十万八千的地方也进入rcu_read_lock()。两者的吞吐量都很大,是否会造成一种接力情况呢?-------也就是说一直都有一个cpu处于rcu_read_lock()中!
      这样是否会造成rcu的错误处理?

哎,就像platinum 说的,看rcu保护的代码时,真的很晕啊!!!

论坛徽章:
0
5 [报告]
发表于 2010-06-02 10:35 |只看该作者
我也是知其然不知其所以然
qiangsheng_cu 兄和 ShadowStar 兄能否写几个例子让我们学习一下如何使用啊?
看了 Document 里的 RCU 文档,又对应看了 net 中的很多实际用法,感觉对不上
出了 rcu_call 外,还有 rcu_dereference,rcu_assign_pointer,完全没有理解……

论坛徽章:
0
6 [报告]
发表于 2010-06-02 11:13 |只看该作者
呵呵,ShadowStar总结的好!
想想,“类似于一个全局的状态标志”,这样更易理解!
call_rcu的时候,检查 ...
qiangsheng_cu 发表于 2010-06-02 10:11


最近刚刚完成一个结合了红黑树和hash表的快速查找模块,用的就是RCU,完全没有用到锁(除了netlink保护用的mutex)。
不过由于职业道德的原因,我无法把代码发布出来。
  1. /**
  2. * rcu_read_lock - mark the beginning of an RCU read-side critical section.
  3. *
  4. * When synchronize_rcu() is invoked on one CPU while other CPUs
  5. * are within RCU read-side critical sections, then the
  6. * synchronize_rcu() is guaranteed to block until after all the other
  7. * CPUs exit their critical sections.  Similarly, if call_rcu() is invoked
  8. * on one CPU while other CPUs are within RCU read-side critical
  9. * sections, invocation of the corresponding RCU callback is deferred
  10. * until after the all the other CPUs exit their critical sections.
  11. *
  12. * Note, however, that RCU callbacks are permitted to run concurrently
  13. * with RCU read-side critical sections.  One way that this can happen
  14. * is via the following sequence of events: (1) CPU 0 enters an RCU
  15. * read-side critical section, (2) CPU 1 invokes call_rcu() to register
  16. * an RCU callback, (3) CPU 0 exits the RCU read-side critical section,
  17. 4) CPU 2 enters a RCU read-side critical section, (5) the RCU
  18. * callback is invoked.  This is legal, because the RCU read-side critical
  19. * section that was running concurrently with the call_rcu() (and which
  20. * therefore might be referencing something that the corresponding RCU
  21. * callback would free up) has completed before the corresponding
  22. * RCU callback is invoked.
  23. *
  24. * RCU read-side critical sections may be nested.  Any deferred actions
  25. * will be deferred until the outermost RCU read-side critical section
  26. * completes.
  27. *
  28. * It is illegal to block while in an RCU read-side critical section.
  29. */
复制代码
上面的是include/linux/rcupdate.h中的说明。

call_rcu确实需要等待所有CPU上的rcu_read_lock都unlock才会调用,也确实会发生您所说的第二种情况。
所以说,RCU是一种延迟调用的处理,不是实时的。

call_rcu确实是在一次上下文切换之后才调用的,我是这么理解的。

评分

参与人数 1可用积分 +18 收起 理由
Godbach + 18 多谢分享

查看全部评分

论坛徽章:
0
7 [报告]
发表于 2010-06-02 11:27 |只看该作者
本帖最后由 ShadowStar 于 2010-06-02 11:38 编辑
我也是知其然不知其所以然
qiangsheng_cu 兄和 ShadowStar 兄能否写几个例子让我们学习一下如何使用啊?
...
platinum 发表于 2010-06-02 10:35


rcu_dereference就是以volatile方式访问指针,以确定的访问内存里的值。
rcu_assign_pointer就是通过内存栅保护写内存。

一段类似的代码如下:
  1. struct rcu_hlist {
  2.     struct rcu_head rcu;
  3.     struct hlist_head[HASH_SIZE];
  4. };

  5. void release_rcu_hlist(struct rcu_head *rcu)
  6. {
  7.     struct rcu_hlist *h = container_of(rcu, struct rcu_hlist, rcu);
  8.     kfree(h);
  9. }

  10. void replace_rcu(struct rcu_hlist **old)
  11. {
  12. struct rcu_hlist *h, *new;
  13. rcu_read_lock();
  14. h = rcu_dereference(*old);
  15. if(h) {
  16.     new = kzalloc(sizeof(struct rcu_hlist), GFP_ATOMIC);
  17.     rcu_assign_pointer(*old, new);
  18.     call_rcu(&h->rcu, release_rcu_hlist);
  19. }
  20. rcu_read_unlock();
  21. }
复制代码

论坛徽章:
0
8 [报告]
发表于 2010-06-02 16:02 |只看该作者
技术上研究,不利用同步原语,又能防止并发操作链表的数据不一致性,有不少研究rcu的paper;网上可以搜到
linux rcu实现利用进程调度的时间差,还是看paper比较完整;

论坛徽章:
0
9 [报告]
发表于 2010-06-02 16:25 |只看该作者
RCU 是不是一般用于极多读,极少写,且所读数据对实时性要求不严格的场景?

论坛徽章:
0
10 [报告]
发表于 2010-06-02 16:45 |只看该作者
本帖最后由 ShadowStar 于 2010-06-02 16:47 编辑
RCU 是不是一般用于极多读,极少写,且所读数据对实时性要求不严格的场景?
platinum 发表于 2010-06-02 16:25


YES

其实现在CPU速度很快了。我觉得所谓“实时”、“非实时”的差别不大。
或者说,一般应用没那么“实时”的要求。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP