新闻详情

新闻详情

首页 / 资讯中心 / 详情

Linux 读-复制-更新 RCU 机制核心原理:Grace Period 与 call_rcu 源码解析

发布时间:2026/9/25 19:33:43来源:尧图网络
Linux 读-复制-更新 RCU 机制核心原理:Grace Period 与 call_rcu 源码解析
Linux 读-复制-更新 RCU 机制核心原理Grace Period 与 call_rcu 源码解析在多核对称多处理SMP架构下即便是最轻量的读写自旋锁rwlock_t或读写信号量rwsem当多个 CPU 核心并发读取共享数据时也必须原子修改内部的读者计数器。这会导致严重的硬件级性能瓶颈不同 CPU 核心的 L1/L2 Cache 行在“修改-失效”之间反复剧烈颠簸Cache Line Bouncing总线带宽被跨核缓存一致性协议如 MESI彻底占满。Linux 内核中的RCURead-Copy-Update读-复制-更新机制是解决极高读并发场景的终极解法。它实现了**“读者零锁、零原子指令、零 Cache 颠簸”**的极致只读性能读端开销低到仅仅是一条关闭抢占的指令。一、RCU 核心三部曲与 Grace Period宽限期模型RCU 将对共享链表或数据结构的更新操作解耦为三个独立阶段1. [Read 端]: 读者自由并发读取老数据 (零阻塞、零锁开销) │ ▼ 2. [Copy Update 端]: 写者复制一份新内存 - 在副本上修改 - 原子替换全局指针 (rcu_assign_pointer) │ ▼ 3. [Grace Period (宽限期)]: 等待所有在指针替换前就已进入读临界区的 CPU 全部退出 │ ▼ 4. [Reclaim 端]: 宽限期结束后安全释放老数据内存 (call_rcu / kfree_rcu)时间轴视角下的宽限期 (Grace Period): CPU 0 (读端): [ rcu_read_lock 读老数据 ] ──(退出)── [Quiescent State (静止态)] │ CPU 1 (写端): --[修改并发布新指针]------------------------[ 宽限期结束: 触发 call_rcu 回调释放老内存 ] ▲ CPU 2 (新读端): [ 读新数据 ] │ │ --------------------------------------------------------------┴──────────────────────── Grace Period (必须覆盖所有旧读者)什么是静止状态Quiescent State, QS在经典非抢占式内核中如果一个 CPU 发生了进程上下文切换schedule()、进入了空闲循环cpu_idle、或者从内核态返回到了用户态就证明该 CPU 绝对不可能还处于rcu_read_lock()与rcu_read_unlock()保护的内核临界区之内。这个状态就称为静止状态QS。当系统中的所有 CPU 核心都至少经历了一次静止状态后一段完整的**宽限期Grace Period**宣告结束。二、读端与写端核心源码剖析1. 读端零开销实现在include/linux/rcupdate.h中读端临界区的实现简洁到令人发指static inline void rcu_read_lock(void) { /* 仅仅关闭当前 CPU 的内核抢占防止临界区内被调度出去 */ preempt_disable(); __acquire(RCU); rcu_lock_acquire(rcu_lock_map); barrier(); /* 编译器内存屏障防止指令重排 */ } static inline void rcu_read_unlock(void) { rcu_lock_release(rcu_lock_map); __release(RCU); preempt_enable(); /* 重新使能内核抢占 */ barrier(); }读者不需要修改任何内存变量不需要发送任何总线消息执行耗时小于 1 纳秒2. 写端指针发布与内存屏障写者通过rcu_assign_pointer宏原子发布新结构体指针内部强制插入写内存屏障smp_store_release确保读者看到新指针时新结构体内部的所有字段已经被完整刷入内存#define rcu_assign_pointer(p, v) \ smp_store_release((p), (v)) #define rcu_dereference(p) \ smp_load_acquire((p))三、异步释放机制call_rcu 源码深度追踪如果在写者路径中调用同步等待synchronize_rcu()写者会被阻塞挂起直到宽限期结束严重影响写吞吐。Linux 内核绝大多数场景使用非阻塞的异步注册函数call_rcu()。1. struct rcu_head 回调节点任何需要通过 RCU 释放的结构体必须内嵌一个struct rcu_headstruct rcu_head { struct rcu_head *next; void (*func)(struct rcu_head *head); /* 宽限期结束后的释放回调函数 */ } __attribute__((aligned(sizeof(void *))));2. call_rcu 入队实现/* kernel/rcu/tree.c */ void call_rcu(struct rcu_head *head, rcu_callback_t func) { unsigned long flags; struct rcu_data *rdp; head-func func; head-next NULL; /* 获取当前 CPU 本地专属的 rcu_data 结构体 */ local_irq_save(flags); rdp this_cpu_ptr(rcu_data); /* 将 rcu_head 挂入本 CPU 的 segcblist (分段回调链表) 尾部 */ rcu_segcblist_enqueue(rdp-cblist, head); /* 若当前积累的回调过多通知 RCU 状态机加速开启新一轮 Grace Period */ if (rcu_segcblist_n_cbs(rdp-cblist) rdp-qhimark) rcu_accelerate_cbs(rdp-rsp, rdp); local_irq_restore(flags); }CPU 本地分段回调链表 (segcblist) 状态演进: [ 刚刚加入 (NEXT_TAIL) ] ── [ 等待当前 GP 结束 (WAIT_TAIL) ] ── [ GP 已完成待执行 (DONE_TAIL) ] │ ▼ 由 RCU 软中断批量执行 free()3. 宽限期结束后的批量回调执行rcu_do_batch当 RCU 核心状态机检测到 Grace Period 结束后会触发RCU_SOFTIRQ软中断调用rcu_do_batch()从DONE_TAIL段取出所有就绪的回调批量执行kfree释放内存。四、RCU 与传统读写锁性能全方位对比对比维度rwlock_t(读写自旋锁)rw_semaphore(读写信号量)RCU (读-复制-更新)读端性能中 (跨核原子修改计数)低 (需原子操作及排队判断)极致 (零总线流量纯只读)读端是否可睡眠否 (自旋锁保护)是 (支持长时间睡眠)经典 RCU 否 (SRCU 支持)写端性能阻塞等待所有读者自旋退出阻塞挂入睡眠等待队列极快 (指针发布异步释放)内存开销极小 (仅一个锁变量)小 (信号量结构体)稍大 (老数据需在宽限期内共存)死锁风险高 (读写锁嵌套易死锁)中读端绝对无死锁可能五、RCU 工业级应用三大铁律读者临界区内绝对禁止睡眠针对 Classic Tree-RCU在rcu_read_lock()和rcu_read_unlock()之间绝对不能调用msleep、mutex_lock或发生阻塞 I/O否则会导致该 CPU 长期无法报告静止状态进而阻断全局 Grace Period造成系统内存无法释放发生 RCU Stall 恐慌。若必须在读端睡眠请使用SRCUSleepable RCU。写者之间仍然需要互斥锁保护RCU 解决的是“读者与写者”之间的并发冲突如果有多个写者同时尝试Copy Update写者之间必须通过互斥锁Mutex或自旋锁Spinlock进行串行化保护。警惕 RCU Stall 告警日志如果内核日志中出现INFO: rcu_preempt detected stalls on CPUs/tasks说明某个 CPU 核心长时间关中断或处于忙死循环中未能及时上报静止状态必须优先排查长耗时循环。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

按钮颜色看着舒服却不一定清楚,做一个对比度检查工具 2026/9/25 20:09:31

按钮颜色看着舒服却不一定清楚,做一个对比度检查工具

设计稿中的颜色在大屏上看着柔和,换到强光环境或小字号时可能已经无法清楚阅读。 实现重点落在颜色强度、预览焦点、深浅模式、对比结果和通过等级,而不是继续增加装饰组件。让前景色、背景色、字号和对比结果共同驱动预览,并给出明确等级。 …

阅读更多 →
Butterbase Durable Objects 深度解析:用有状态 Actor 构建聊天室与长时运行 Agent 2026/9/25 20:09:24

Butterbase Durable Objects 深度解析:用有状态 Actor 构建聊天室与长时运行 Agent

Butterbase Durable Objects 深度解析:用有状态 Actor 构建聊天室与长时运行 Agent 【免费下载链接】butterbase-oss Open-source backend-as-a-service. Postgres, auth, storage, functions, AI gateway, MCP. 项目地址: https://gitcode.com/gh_mirrors/bu/but…

阅读更多 →
OpenCodex Providers 工作区账户与导航基线审计——从契约证据到多账户激活场景的全链路梳理 2026/9/25 20:08:59

OpenCodex Providers 工作区账户与导航基线审计——从契约证据到多账户激活场景的全链路梳理

【免费下载链接】opencodex Universal provider proxy for OpenAI Codex & Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code 项目地址: https://gitcode.com/gh_mirrors/ope/opencodex 点击…

阅读更多 →
Navicat for MySQL实战指南:安装、连接、导入导出与排错 2026/9/25 20:08:39

Navicat for MySQL实战指南:安装、连接、导入导出与排错

简介:Navicat for MySQL是专为MySQL设计的图形化数据库管理及开发工具,主要面向数据库管理员、运维开发者和需要日常操作MySQL的人员。它提供直观的图形界面与丰富功能,包括多连接管理、SQL语法高亮与自动完成、可视化ER模型、数据导入导出、…

阅读更多 →
校园WiFi覆盖方案设计:AC+瘦AP、信道规划与POE供电避坑 2026/9/25 20:08:39

校园WiFi覆盖方案设计:AC+瘦AP、信道规划与POE供电避坑

简介:面向学校信息化建设者与无线网络工程师,这份PDF文档提供了一套完整的校园无线WIFI覆盖需求综合解决方案。内容从项目概述、需求分析到室内外覆盖规划、产品选型与网络拓扑规划均有详细展开,重点涵盖设计原则(实用、可靠、安全…

阅读更多 →
基于 FluxCD 的多集群 GitOps 声明式配置同步与灾难恢复 2026/9/25 20:08:33

基于 FluxCD 的多集群 GitOps 声明式配置同步与灾难恢复

基于 FluxCD 的多集群 GitOps 声明式配置同步与灾难恢复在构建跨越多个物理数据中心(如华东核心主集群 k8s-prod-east 华北异地容灾集群 k8s-prod-north)的企业级高可用架构时:如何确保两套物理隔离的 Kubernetes 集群中的 300 多个微服务配…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉