linux的RCU机制

RCU(Read-Copy Update)是 Linux 内核中非常重要、也非常巧妙的一种 高效读写同步机制

RCU 的目标

  • 让读者 无锁、极快地读取数据

  • 写者在更新数据时也 不会阻塞读者

RCU 的核心概念和主要 API

  • 读侧临界区(Read-Side Critical Section)
    指的是被 rcu_read_lock()rcu_read_unlock() 包围的区域。
    在这个区域里,读者可以安全访问旧数据。

  • 宽限期(Grace Period)
    指的是系统保证“所有正在进行的读者(此处的读者包括写者)都已经退出”的时间段。
    一旦宽限期结束,表示没有人再访问旧数据,这时旧数据可以安全释放。

API 作用
rcu_read_lock() / rcu_read_unlock() 标记 RCU 读侧临界区
rcu_dereference(p) 安全读取 RCU 保护的指针
rcu_assign_pointer(p, v) 安全更新指针,发布新版本
synchronize_rcu() 等待所有旧读者退出临界区(同步点)
call_rcu(cb, func) 注册回调函数,在宽限期结束后执行(延迟释放)

流程

读者

  1. 调用 rcu_read_lock() 进入读侧临界区

    • 在非可抢占 RCU 实现中,会执行 preempt_disable(),禁止任务被抢占。
  2. rcu_dereference() 读取数据

  3. 调用 rcu_read_unlock() 离开读侧临界区

写者

  1. 拷贝旧数据;

  2. 修改副本(直接用 rcu_dereference() 读取数据)

  3. rcu_assign_pointer() 替换指针;

  4. call_rcu()synchronize_rcu() 等待旧读者退出;

  5. 释放旧数据。

核心难点之一:写操作和新读者的并发一致性问题

考虑以下情况

  1. 写者复制一份副本,在副本上修改;

  2. 还没把新副本放回去(即还没执行 rcu_assign_pointer());

  3. 此时有新的读者来了;

  4. 新读者会通过 rcu_dereference() 读到 旧数据

  5. 那新读者读到旧数据怎么办?是不是不一致?

结论

RCU 允许读者在短时间内读到“旧数据”,但保证数据永远一致、不会崩。 换句话说: RCU 保证一致性(Consistency),但不保证最新性(Freshness)。

1 个赞

前排围观