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

  • 如何查看 Linux 内核中当前使用 RCU 的位置?

    搜索“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)。