如何理解 RCU宽限期Grace period
RCU(Read-Copy-Update,读-复制-更新)是 Linux 内核中一种高效的同步机制,特别适用于读多写少的并发场景。其核心优势在于读操作完全无锁、无阻塞,极大提升了读性能。而实现这一优势的关键,就在于 Grace Period(宽限期) 的概念。
一、Grace Period 的核心定义
Grace Period(宽限期) 是指:从写操作开始更新数据指针的那一刻起,到系统中所有 CPU 都至少经历过一次“静默状态”(Quiescent State)为止的这段时间。
- 静默状态(Quiescent State):一个 CPU 不在 RCU 读临界区内的状态。例如:
- 发生了进程上下文切换。
- 进入了空闲循环(idle)。
- 禁用了抢占(preemption)后重新启用。
✅ 关键结论:一旦一个 CPU 进入了静默状态,就说明它不可能再持有对旧数据的引用。
二、为什么需要 Grace Period?
RCU 的基本流程如下:
-
读操作:
rcu_read_lock(); data = rcu_dereference(ptr); // 读取受保护的指针 // 使用 data... rcu_read_unlock(); -
写操作:
new_data = kmalloc(...); memcpy(new_data, old_data, ...); // 复制并修改 rcu_assign_pointer(ptr, new_data); // 原子替换指针 synchronize_rcu(); // 等待宽限期结束 kfree(old_data); // 安全释放旧数据
问题来了:为什么不能在 rcu_assign_pointer 之后立即 kfree(old_data)?
因为:
- 在写操作执行
rcu_assign_pointer之前,可能已经有多个读线程正在使用old_data。 - 由于读操作是无锁的,写线程无法知道“谁还在读”、“什么时候读完”。
- 如果立即释放
old_data,正在读取它的线程就会访问已释放的内存 → Use-After-Free,严重 bug!
Grace Period 的作用就是:确保所有在更新指针之前已经开始的读操作,都已经结束。
一旦 Grace Period 结束,就可以安全地回收旧数据。
三、Grace Period 如何工作?(以 Linux 内核为例)
Linux 内核使用 Tree RCU 机制来高效地跟踪 Grace Period,其核心思想是:
-
写者发起更新:
- 调用
rcu_assign_pointer()原子地更新指针。 - 同步请求:调用
synchronize_rcu(),请求等待当前 Grace Period 结束。为阻塞调用,可能耗时较长(毫秒级),不要在中断上下文或实时性要求高的路径中使用。 - 异步请求:调用
call_rcu(),将回调函数注册到 Grace Period 结束时执行,为非阻塞调用。
- 调用
-
内核启动 Grace Period:
- 内核后台线程(
rcu_gp_kthread)检测到有新的更新请求,启动一个新的 Grace Period。
- 内核后台线程(
-
检测静默状态:
- 每个 CPU 定期检查自己是否进入过静默状态(如发生调度、进入 idle)。
- 一旦某个 CPU 进入静默状态,就向 RCU 子系统报告。
-
Grace Period 结束:
- 当所有 CPU 都报告了至少一次静默状态后,内核判定当前 Grace Period 结束。
- 此时可以安全调用
kfree(old_data)回收内存。
四、一个形象的比喻
想象一个图书馆:
- 读者:可以随时进入图书馆看书(
rcu_read_lock),看完离开(rcu_read_unlock)。 - 管理员(写者):想把一本旧书换成新版本。
流程:
- 管理员复印一本新书(Copy)。
- 把书架上的旧书换成新书(Update)。
- 但旧书不能立刻扔掉!因为可能还有读者正在看它。
- 管理员等待所有读者都至少离开过一次图书馆(Grace Period)。
- 一旦所有人都离开过,就可以安全地销毁旧书(Reclaim)。
📌 Grace Period 就是“等待所有人至少离开一次图书馆”的时间段。
五、Grace Period 的特点
| 特性 | 说明 |
|---|---|
| 非实时性 | synchronize_rcu() 可能阻塞较长时间,取决于系统负载。 |
| 可重叠 | 多个 Grace Period 可以部分重叠,提高效率。 |
| 批量处理 | 多个写操作可以共享同一个 Grace Period,减少等待次数。 |
| CPU 敏感 | 即使只有一个 CPU 长时间不进入静默状态(如死循环),Grace Period 也无法结束。 |
六、总结
- Grace Period 是 RCU 实现“无锁读”的基石。
- 它通过等待所有 CPU 进入静默状态,确保旧数据不再被任何读者引用。
- 写者必须等待 Grace Period 结束后,才能安全回收旧内存。
- 这种“延迟回收”机制,使得读操作完全无锁,极大提升了读性能。
✅ 一句话总结:
Grace Period 是一个“安全等待期”,确保所有可能引用旧数据的读者都已经退出,之后才能回收旧数据。
948

被折叠的 条评论
为什么被折叠?



