RCU 概念¶
RCU(读取-复制更新)背后的基本思想是将破坏性操作分为两部分:一部分阻止任何人看到正在被破坏的数据项,另一部分实际执行破坏。这两部分之间必须经过一个“宽限期”,并且这个宽限期必须足够长,以确保访问被删除项的任何读取者都已经放弃了他们的引用。 例如,从链接列表中受 RCU 保护的删除将首先从列表中删除该项,等待宽限期过去,然后释放该元素。 有关将 RCU 与链接列表一起使用的更多信息,请参见 使用 RCU 保护主要为读取操作的链接列表。
常见问题解答¶
为什么有人想使用 RCU?
RCU 的两部分方法的优点是,RCU 读取者无需获取任何锁,执行任何原子指令,写入共享内存,或者(在 Alpha 以外的 CPU 上)执行任何内存屏障。 事实上,这些操作在现代 CPU 上非常昂贵,这正是 RCU 在主要为读取操作的情况下具有性能优势的原因。 RCU 读取者无需获取锁的事实还可以大大简化避免死锁的代码。
如果 RCU 读取者没有指示他们何时完成,那么更新者如何知道宽限期何时完成?
与自旋锁一样,RCU 读取者不允许阻塞、切换到用户模式执行或进入空闲循环。 因此,一旦看到 CPU 正在经历这三种状态中的任何一种,我们就知道该 CPU 已经退出了任何先前的 RCU 读取端关键区域。 因此,如果我们从链接列表中删除一个项目,然后等待所有 CPU 切换上下文、在用户模式下执行或在空闲循环中执行,我们可以安全地释放该项目。
RCU 的可抢占变体 (CONFIG_PREEMPT_RCU) 具有相同的效果,但要求读取者操作 CPU 本地计数器。 这些计数器允许在 RCU 读取端关键区域内进行有限类型的阻塞。 SRCU 也使用 CPU 本地计数器,并允许在 RCU 读取端关键区域内进行一般阻塞。 RCU 的这些变体通过采样这些计数器来检测宽限期。
如果我在单处理器内核上运行,它一次只能做一件事,为什么我应该等待宽限期?
有关更多信息,请参见 单处理器系统上的 RCU。
我如何查看 RCU 当前在 Linux 内核中的使用位置?
搜索“rcu_read_lock”、“rcu_read_unlock”、“call_rcu”、“rcu_read_lock_bh”、“rcu_read_unlock_bh”、“srcu_read_lock”、“srcu_read_unlock”、“synchronize_rcu”、“synchronize_net”、“synchronize_srcu”和其他 RCU 原语。 或者从以下位置获取 cscope 数据库之一
(http://www.rdrop.com/users/paulmck/RCU/linuxusage/rculocktab.html)。
编写使用 RCU 的代码时,我应该遵循哪些准则?
参见 RCU 补丁的审查清单。
为什么命名为“RCU”?
“RCU”代表“读取-复制更新”。 使用 RCU 保护主要为读取操作的链接列表 有关此名称来源的更多信息,搜索“read-copy update”即可找到。
我听说 RCU 有专利? 那是什么情况?
是的,它是。 有几个与 RCU 相关的已知专利,请在 Documentation/RCU/RTFP.txt 中搜索字符串“Patent”以找到它们。 其中,一项已被受让人放弃,其他已被贡献给 GPL 下的 Linux 内核。 许多(但不是全部)早已过期。 现在还有用户级 RCU 的 LGPL 实现可用 (https://liburcu.org/)。
我听说 RCU 需要进行一些工作才能支持实时内核?
通过 CONFIG_PREEMPTION 内核配置参数启用对实时友好的 RCU。
在哪里可以找到有关 RCU 的更多信息?
参见 Documentation/RCU/RTFP.txt 文件。 或者将您的浏览器指向 (https://docs.google.com/document/d/1X0lThx8OK0ZgLMqVoXiR4ZrGURHrXK6NyLRbeXe3Xac/edit) 或 (https://docs.google.com/document/d/1GCdQC8SDbb54W1shjEXqGZ0Rq8a6kIeYutdSIajfpLA/edit?usp=sharing)。