1

Linux 内核中的核心 RCU API 适用于内核中的所有客户端,这意味着任何读取器(即使他们正在访问完全不相关的数据结构)访问 rcu 支持的数据都将被平等对待。并且像 synchronize_rcu() 这样的调用需要等待所有的读者,即使他们在后台访问完全不相关的数据结构。

为什么 Linux 内核从未添加对每个数据对象 RCU 的支持?我在这里错过了什么吗?我认为当前 RCU API 的含义是,如果内核中有很多客户端,则 RCU 的整体性能可能会受到影响,因为它们共享全局视图。

4

2 回答 2

0

我认为当前 RCU API 的含义是,如果内核中有很多客户端,则 RCU 的整体性能可能会受到影响,因为它们共享全局视图。

不,这是错误的暗示。Linux 内核中的 RCU 实现对于“客户端”的数量是完全可扩展的。

您想用多个锁对象“替换”用于 RCU 的单个“锁对象”,因此可以使用不同的锁对象来保护不同的数据。但是 RCU 实现根本不使用任何锁对象!

正因为如此,RCU 的实现相当复杂,并且使用了 Linux 内核的内部细节(例如调度程序),但这是值得的。例如rcu_read_lock,由于不存在与其他内核的内存争用,因此rcu_read_unlock工作速度比任何类型的都快得多。spin_lock


实际上,“锁定对象”用于RCU ( sRCU ) 的可睡眠版本。参见例如那篇文章

于 2020-12-16T16:15:33.073 回答
0

我最近一直在问自己同样的问题,我的推理如下:

  • rcu_synchronize()仅等待在调用 RCU 关键部分时已经参与其中的读者,因此“新”客户端不是问题
  • 不允许在 RCU 临界区中阻塞,因此读者不会长时间阻塞rcu_synchronize()
  • 其他“竞争者”数量有限:每个逻辑 CPU 最多 1 个

如果我的理解/推理是正确的,我怀疑可能争用的开销仍然足够低,不足以证明使用特定于客户端的 RCU 锁是合理的。我不知道这将如何与大量 CPU 一起扩展。

这是基于我对内核代码的理解和阅读,假设CONFIG_TREE_RCU。事情可能会随着其他实现而改变(例如,使用CONFIG_TINY_RCUsynchronize_rcu()是……空的???)。此外,在某些特定情况下,AFAIU 可能会在 critsec 内发生抢占(例如,使用CONFIG_PREEMPT_RCU?)。我不知道这是否会改变很多事情,但不要指望它会改变(因为可能只有更高优先级的任务才能抢占 RCU critsec?)。

于 2021-10-14T13:55:30.193 回答