惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
阮一峰的网络日志
阮一峰的网络日志
博客园 - 聂微东
F
Fortinet All Blogs
H
Help Net Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
DataBreaches.Net
MyScale Blog
MyScale Blog
B
Blog
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
GbyAI
GbyAI
Google DeepMind News
Google DeepMind News
IT之家
IT之家
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
博客园_首页
L
LangChain Blog
V
V2EX
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Blog of Author Tim Ferriss
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - Franky

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解
PREEMPT_RT补丁技术实现:RCU
阿百山 · 2026-04-22 · via 博客园_首页

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的实现机制。

#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期间无须禁用抢占