尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Linux 内核的 Context Tracking上下文跟踪
Linux 内核的Context Tracking上下文跟踪也叫 CT / EQoS — Extended Quiescent State​ 是内核用来精确感知 CPU 当前运行在哪个执行域用户态 / 内核态 / 空闲 / Guest VM并通知 RCU 和 虚拟时间记账子系统做相应处理的基础设施。它是NO_HZ_FULL全动态无滴答 tickless能正常工作的前提。下面从数据结构、核心原理、关键流程、与 RCU 的关系四个层面详细说明。一、Context Tracking 解决什么问题传统 RCU 依赖周期性的 timer tick调度时钟中断来判断某 CPU 是否经过 quiescent state经历用户态或 idle。但在NO_HZ_FULL模式下tick 被停止了——RCU 无法靠 tick 感知 CPU 进入/离开用户空间。Context Tracking 的作用就是在体系结构入口/出口syscall/异常/中断返回用户态、idle 进入/退出显式通知内核​ 本 CPU 现在进入/退出用户态或 idle/GUEST让 RCU 可以把用户态当作 Extended Quiescent StateEQS从而安全停止对该 CPU 的 grace-period 追踪也允许停掉周期性 tick。此外它还驱动vtimeVirtual Time Accounting区分进程在用户态 / 内核态 / guest 的耗时TASKS_RCU / TRACE_RCU标记任务不在内核临界区二、核心数据结构每 CPU 一个struct context_tracking新内核重命名为struct ct_rcu原理相同// include/linux/context_tracking.h context_tracking_state.h struct context_tracking { bool active; // 该 CPU 是否启用 context tracking (在 NO_HZ_FULL mask 中) atomic_t state; // 当前上下文状态 RCU watching 位 /* 旧版用 enum { IN_KERNEL0, IN_USER } state; */ }; DEFINE_PER_CPU(struct context_tracking, context_tracking);state在新内核5.x/6.x是一个atomic_t其低位编码RCU_WATCHING bitRCU 是否在观察本 CPU1watching, 0in EQS上下文类型KERNEL / USER / IDLE / GUEST全局静态键context_tracking_enabledStatic Key确保未开启CONFIG_CONTEXT_TRACKING_USER或 CPU 不在 dyntick mask 时零开销跳过。三、关键状态转换与调用点状态机┌──────────────┐ ct_user_enter() ┌──────────────┐ │ IN_KERNEL │ ──────────────────▶ │ IN_USER │ │ (RCU watching)│ ◀────────────────── │(RCU EQS/off) │ └──────────────┘ ct_user_exit() └──────────────┘ ▲ │ ▲ │ │ │ ct_idle_enter/exit() │ │ │ ▼ │ ▼ IDLE (也是一种 EQS)IN_KERNELCPU 执行内核代码 → RCU 正常监视rcu_irq_enter 类语义IN_USER / IDLE / GUESTCPU 不在内核 → RCU 认为这是Extended Quiescent State可停止 grace period 对该 CPU 的等待体系结构入口处的埋点场景汇编/早期 C 入口调用内核→用户态返回syscall/exception 返回ct_user_enter()/user_enter_irqoff()用户态→内核syscall/异常进入ct_user_exit()/user_exit_irqoff()idle loop 进入ct_idle_enter()→rcu_eqs_enter()idle loop 退出ct_idle_exit()→rcu_eqs_exit()KVM guest 进入/退出ct_guest_enter()/ct_guest_exit()这些函数通常在noinstr标记的入口代码中调用IRQs off在 RCU 开始/停止 watching 的前后。四、核心函数工作流程以用户态进出为例新内核__ct_user_enter/__ct_user_exit旧版context_tracking_user_enter/exit1.ct_user_enter()— 内核 → 用户态ct_user_enter(CONTEXT_USER): 若 !context_tracking_enabled() → return 若 in_interrupt() → return // 嵌套 IRQ 中不处理 若 state 已是 IN_USER → return // 幂等 ── 以下 this_cpu active true ── vtime_user_enter(current) // 停止内核时间记账开始用户时间 rcu_user_enter() // ★ 通知 RCU 进入 Extended Quiescent State → ct_kernel_exit_state() // 递增 dynticks 计数器清除 RCU_WATCHING 位 this_cpu_write(state, IN_USER)关键点rcu_user_enter()使 RCU 对该 CPU 不再 watching该 CPU 被视为已通过 quiescent state后续不需要 tick。2.ct_user_exit()— 用户态 → 内核syscall/异常ct_user_exit(CONTEXT_USER): 若 !enabled → return 若 in_interrupt() → return 若 state ! IN_USER → return (已在内核幂等) ── this_cpu active true ── rcu_user_exit() // ★ 通知 RCU 退出 EQS → ct_kernel_enter_state() // 递增 dynticks设置 RCU_WATCHING 位 vtime_user_exit(current) // 恢复内核时间记账 this_cpu_write(state, IN_KERNEL)必须在任何 RCU read-side critical section 之前调用否则会读到已停用的 RCU。3. 异常嵌套处理 —exception_enter()/exception_exit()// include/linux/context_tracking.h static inline enum ctx_state exception_enter(void) { prev __ct_state(); // 读取当前状态 if (prev ! CT_STATE_KERNEL) // 若原在 USER先退出 USER ct_user_exit(prev); return prev; } static inline void exception_exit(enum ctx_state prev) { if (prev ! CT_STATE_KERNEL) ct_user_enter(prev); // 异常返回时恢复 USER 状态 }保证异常发生在用户态时短暂把 context 切回 KERNEL让 RCU watching返回时再切回去。4. 任务切换时的处理void context_tracking_task_switch(prev, next) { if (ct-active) { clear_tsk_thread_flag(prev, TIF_NOHZ); set_tsk_thread_flag(next, TIF_NOHZ); } }TIF_NOHZ使新任务走 syscall slow path从而在返回用户态时触发ct_user_enter()检查。init 进程启动时设TIF_NOHZ通过 fork 继承给所有进程。五、与 RCU 的协作关系Context Tracking 动作RCU 对应行为rcu_user_enter()→ct_kernel_exit_state()dynticks 计数器RCU_WATCHING0 → CPU 进入 EQSRCU 可报告该 CPU 已过 quiescent statercu_user_exit()→ct_kernel_enter_state()dynticks 计数器RCU_WATCHING1 → RCU 恢复监视grace period 继续等待该 CPUrcu_irq_enter()/exit()处理中断中嵌套dynticks_nmi_nesting 独立维护不影响 user eqsrcu_is_watching_curr_cpu()直接读context_tracking.state的 RCU_WATCHING 位判断。六、配置与激活条件编译CONFIG_CONTEXT_TRACKING_USERy隐含CONFIG_NO_HZ_FULLy启动参数nohz_fullcpulist— 指定哪些 CPU 激活context_tracking.activetrueCONTEXT_TRACKING_FORCE强制所有 CPU 开启调试用非nohz_fullCPU 上activefalse只维护 state 用于一致性不调rcu_user_enter/exit开销接近零。七、一句话总结Context Tracking 是内核在用户态↔内核态 / idle / guest 边界插入的探针通过维护每 CPU 的上下文状态并告知 RCU 进入/退出 Extended Quiescent State使得 NO_HZ_FULL CPU 在用户态运行时可以停掉周期 tick 且 RCU grace period 仍能正确结束同时驱动进程虚拟时间vtime精确记账。
RELATED

相关推荐

北京华恒智信为物业服务行业破解基层人员老龄化、低认同、高流失难题

北京华恒智信为物业服务行业破解基层人员老龄化、低认同、高流失难题

保洁、保安人员是物业服务中与业主接触最频繁的基层岗位群体,但该类岗位长期面临极高的人员流失问题。究其核心原因,并非薪资待遇不足,而是基层从业人员普遍缺乏职业尊重与职业认同感,这也成为困扰众多物业服务企业的核心痛点。多…

📅 2026/11/9 4:12:46
百度网盘秒传革命:3步实现永久文件分享,告别重复上传

百度网盘秒传革命:3步实现永久文件分享,告别重复上传

百度网盘秒传革命:3步实现永久文件分享,告别重复上传 【免费下载链接】rapid-upload-userscript-doc 秒传链接提取脚本 - 文档&教程 项目地址: https://gitcode.com/gh_mirrors/ra/rapid-upload-userscript-doc 你是否有过这样的经历&#xf…

📅 2026/11/9 4:12:46
如何将微信聊天记录变成珍贵数字记忆:WeChatMsg实用指南

如何将微信聊天记录变成珍贵数字记忆:WeChatMsg实用指南

如何将微信聊天记录变成珍贵数字记忆:WeChatMsg实用指南 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeC…

📅 2026/9/11 17:59:14
MORE NEWS

更多资讯

📰

温州电工证报考时间怎么安排?郑州报考避坑指南帮你理清流程

温州电工证报考时间怎么安排?郑州报考避坑指南帮你理清流程 实操考试心里没底怕挂科,这几乎是每个准备考电工证的朋友心里的疙瘩。特别是像你这样,刚毕业的郑州工程类学生,面对第一次实操考试,焦虑是正常的。温州电工证报考时间虽然固定,但具体怎么安排…

📰

技工学校电工证考证不知道去哪报名怕被中介坑的良心建议

技工学校电工证考证不知道去哪报名怕被中介坑的良心建议 你是不是正在为【技工学校电工证考证】发愁?找培训机构怕被坑,自己又不清楚流程,担心花冤枉钱还拿不到证?别急,我用10年经验告诉你,这事儿真不难。…

📰

高压电工证含金量高怎么考?考前押题帮你搞定

高压电工证含金量高怎么考?考前押题帮你搞定 证书过期了不知道怎么复审延期,这事儿千万别拖。高压电工证含金量高,但一旦过期就失去效力,不仅影响日常工作,还可能面临罚款或停工。很多持证人因为不了解流程,错失了复审时间。其实,复审并不复杂,关键是…

📰

廊坊大城电工证怎么考?全国通用的证书怎么用?

廊坊大城电工证怎么考?全国通用的证书怎么用? 你是不是正愁手里没有特种作业证,连面试机会都拿不到?现在电工证成了很多行业的准入门槛, 廊坊大城电工证 因为 全国通用…

📰

电工证台州复审延期怎么办理

台州电工证怕考不过白交培训费?看看郑州报考避坑指南 怕考不过白交培训费?别急,台州电工证考前准备做对了,90%的人都能一次通过。很多人报名前对考试流程、内容、题型、复习资料一知半解,结果考试挂了,培训费打了水漂。如果你是驻马店的应届工程类毕…

📰

南昌去哪里考电工证好怎么报名 电工证实操考试心里没底怕挂科怎么办

南昌去哪里考电工证好怎么报名 电工证实操考试心里没底怕挂科怎么办 实操考试心里没底怕挂科,这是大多数第一次考电工证的朋友的真实写照。尤其是对于在南昌从事电工相关工作的朋友们来说,不管是低压还是高压电工证,拿到手才真正能上工地、进项目,否则只…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬