PREEMPT_RT补丁技术实现:RCU

RCU (Read-Copy Update, 读 - 复制 - 更新) 是 Linux 内核中一种专为 读多写少 场景优化的高性能同步机制。它的核心优势是:读操作完全无锁、零开销,写操作通过延迟回收保证安全,极大提升多核并发效率。

一、核心原理

RCU 将更新操作拆分为 移除(替换)回收(释放) 两个阶段,并引入 宽限期(Grace Period) 确保安全。

读端(Reader)

  • 无锁访问 :读者通过 rcu_read_lock()rcu_read_unlock() 标记临界区,无需获取锁,直接访问数据。
  • 可见性 :读者要么看到旧版本,要么看到新版本,永远不会读到中间状态

写端(Writer)

  1. Copy(复制):不直接修改原数据,而是创建一份副本并修改。
  2. Modify(修改):在副本上完成所有更新。
  3. Assign(替换) :用原子操作(rcu_assign_pointer)将全局指针指向新副本。此后,新读者只能看到新数据。
  4. Wait(等待) :进入宽限期,等待所有正在访问旧数据的读者完成读取。
  5. Reclaim(回收):宽限期结束后,安全释放旧数据。

关键概念:宽限期 (Grace Period)

  • 定义:从指针替换完成,到所有 CPU 都退出读临界区的时间窗口。
  • 作用:确保旧数据在没有任何读者引用时才被释放,避免悬空指针(Use-After-Free)。
  • 静默状态(Quiescent State):内核将上下文切换、进入用户态、空闲循环,视为 CPU 已退出读临界区的标志。

二、适配PREEMPT_RT的 RCU 配置

在主线 Linux 内核中,RCU 的大量处理工作运行在软中断上下文,此过程抢占是关闭的,会造成显著延迟、损害实时性。这篇文章总结了一些相关的优化设置:RCU Configuration for Real-Time Systems, 简单总结一下就是以下的一些设定:

  • RCU 回调卸载(RCU Callback Offloading)
  • RCU 优先级提升(RCU Priority Boosting)
  • RCU 加速宽限期(Expedited RCU Grace Periods)
  • 可抢占 RCU(Preemptible RCU)

三、 可抢占 RCU(Preemptible RCU)

对于RCU的一些优化操作,我想着重介绍一下Preemptible RCU的实现机制。

c 复制代码
#ifdef CONFIG_PREEMPT_RCU
static void rcu_preempt_read_enter(void)
{
	WRITE_ONCE(current->rcu_read_lock_nesting, READ_ONCE(current->rcu_read_lock_nesting) + 1);
}
/*
 * Preemptible RCU implementation for rcu_read_lock().
 * Just increment ->rcu_read_lock_nesting, shared state will be updated
 * if we block.
 */
void __rcu_read_lock(void)
{
	rcu_preempt_read_enter();
	if (IS_ENABLED(CONFIG_PROVE_LOCKING))
		WARN_ON_ONCE(rcu_preempt_depth() > RCU_NEST_PMAX);
	if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD) && rcu_state.gp_kthread)
		WRITE_ONCE(current->rcu_read_unlock_special.b.need_qs, true);
	barrier();  /* critical section after entry code. */
}
#else /* #ifdef CONFIG_PREEMPT_RCU */

static inline void __rcu_read_lock(void)
{
	preempt_disable();
}

#endif

通过上述代码对__rcu_read_lock的实现不难看出区别:

  • Preemptible RCU对比普通RCU, 将preempt_disable替换成current->rcu_read_lock_nesting的嵌套层级计数。
  • 普通RCU判断宽限期结束通过判断当前是否处于禁止抢占 的状态,而PREEMPT_RCU则通过判断嵌套层级 来确认是否可以回收旧数据。通过标记临界区方法的改变,使rcu_read_lock期间无须禁用抢占
相关推荐
Industio_触觉智能6 个月前
RK3562核心板/开发板RT-Linux系统实时性及硬件中断延迟测试
linux·嵌入式开发·瑞芯微·rk3562·rt linux·xenomai rt·preempt_rt