KiIdleLoop 函数分析
KiIdleLoop 函数分析概述KiIdleLoop是 ReactOS 内核空闲线程的主循环。当 CPU 上没有任何可运行的线程时调度器选择空闲线程运行进入此循环。它永不返回是引导 CPU 在完成KiInitializeKernel后进入的最终状态。文件[ke/i386/thrdini.c#L260](file:///d:/reactos/ntoskrnl/ke/i386/thrdini.c#L260)KiSystemStartupBootStack() [kiinit.c:691] └─ KiInitializeKernel() [kiinit.c:433] └─ ExpInitializeExecutive() └─ PsCreateSystemThread(Phase1Initialization) └─ Thread-Priority 0 └─ KiIdleLoop() [thrdini.c:260] └─ 永不返回完整源码DECLSPEC_NORETURN VOIDKiIdleLoop(VOID){PKPRCB PrcbKeGetCurrentPrcb();PKTHREAD OldThread,NewThread;/* Now loop forever */while(TRUE){/* Start of the idle loop: enable interrupts briefly */_enable();YieldProcessor();// PAUSE/HALT 提示YieldProcessor();_disable();/* Check for pending work */if((Prcb-DpcData[0].DpcQueueDepth)||(Prcb-TimerRequest)||(Prcb-DeferredReadyListHead.Next)){/* Clear DPC software interrupt */HalClearSoftwareInterrupt(DISPATCH_LEVEL);/* Process all pending DPCs */KiRetireDpcList(Prcb);}/* Check if a thread is ready to run */if(Prcb-NextThread){_enable();OldThreadPrcb-CurrentThread;// 空闲线程自己NewThreadPrcb-NextThread;// 要切换到的线程Prcb-NextThreadNULL;Prcb-CurrentThreadNewThread;NewThread-StateRunning;KiSwapContext(APC_LEVEL,OldThread);// ← 上下文切换}else{/* No work — let HAL put CPU to sleep */Prcb-PowerState.IdleFunction(Prcb-PowerState);}}}执行流程分析循环前 — 中断短暂使能并暂停_enable(); // sti — 开中断让挂起的中断有机会被处理 YieldProcessor(); // pause 指令 — 提示 CPU 处于自旋等待 YieldProcessor(); _disable(); // cli — 关中断检查共享状态前关中断YieldProcessor()在 x86 上映射为_mm_pausePAUSE 指令作用是提示 CPU 当前处于自旋等待循环优化流水线避免内存顺序违规的惩罚在 Hyper-Threading 场景尤其重要等同于__asm__ __volatile__(pause);短暂的sti使中断在空闲循环顶部能被响应之后cli关中断再检查共享数据结构DPC 队列、定时器请求、就绪线程链表符合关中断访问内核调度数据结构的规范。分支 A有挂起工作 — 处理 DPCif((Prcb-DpcData[0].DpcQueueDepth)||(Prcb-TimerRequest)||(Prcb-DeferredReadyListHead.Next)){HalClearSoftwareInterrupt(DISPATCH_LEVEL);KiRetireDpcList(Prcb);}检查三个条件条件含义DpcQueueDepth当前 CPU 的 DPC 队列中有待处理的延迟过程调用TimerRequest有定时器过期需要更新重计算就绪线程优先级等DeferredReadyListHead.Next有延迟就绪的线程等待被插入调度数据库如果任一条件为真HalClearSoftwareInterrupt(DISPATCH_LEVEL)— 清除 DPC 软件中断请求避免重复触发KiRetireDpcList(Prcb)— 执行所有挂起的 DPC同时处理定时器请求和延迟就绪线程KiRetireDpcList完成后可能已经有线程被加入Prcb-NextThread因此不会直接 fallthrough 到检查 NextThread 的分支而是从头开始下一轮循环。分支 B有待切换线程 — 上下文切换if(Prcb-NextThread){_enable();// 切换前开中断OldThreadPrcb-CurrentThread;// 空闲线程NewThreadPrcb-NextThread;// 要切换到的线程Prcb-NextThreadNULL;// 清空Prcb-CurrentThreadNewThread;NewThread-StateRunning;// 标记为运行中KiSwapContext(APC_LEVEL,OldThread);// ← ★ 上下文切换 ★}关键变量Prcb-CurrentThread— 当前 CPU 正在执行的线程空闲线程Prcb-NextThread— 调度器KiQuantumEnd/KiDispatchInterrupt/KiRetireDpcList等选择的下一个要运行的线程KiSwapContext 调用链KiSwapContext(APC_LEVEL, OldThread) [ctxswitch.S:79] └─ KiSwapContextInternal └─ KiSwapContextEntry(KSWITCHFRAME, OldThread~) ├─ 保存 OldThread-KernelStack ESP └─ KiSwitchThreads(OldThread, NewThread-KernelStack) mov esp, NewThread-KernelStack ← ★ 切换栈 └─ KiSwapContextExit(OldThread) ├─ 检查进程切换 → 切换 CR3 ├─ TSS.Esp0 NewThread-InitialStack ├─ TEB 设置 └─ 异常链 恢复非易失寄存器 ret → KiThreadStartup (新线程的 CtxSwitchFrame.RetAddr)KiSwapContext 返回后KiSwapContext返回时CPU 已经在新线程的栈上。OldThread参数就是当前的空闲线程这意味着当空闲线程下次被调度时KiSwapContext会返回到KiIdleLoop中KiSwapContext的下一行空闲循环继续执行while (TRUE)的下一轮迭代分支 C无工作 — 空闲节能else{Prcb-PowerState.IdleFunction(Prcb-PowerState);}当既无 DPC/定时器待处理也无就绪线程时调用空闲节能函数。PopIdle0[power.c#L501](file:///d:/reactos/ntoskrnl/po/power.c#L501)VOID FASTCALLPopIdle0(IN PPROCESSOR_POWER_STATE PowerState){HalProcessorIdle();}HalProcessorIdle[halx86/pic/processor.c#L46](file:///d:/reactos/hal/halx86/pic/processor.c#L46)VOID NTAPIHalProcessorIdle(VOID){_enable();// sti — 开中断__halt();// hlt — 暂停 CPU 直到下一个外部中断}HLT 指令的作用CPU 暂停执行进入低功耗模式等待下一个外部中断硬件中断或 IPI唤醒中断触发后CPU 继续执行HalProcessorIdle的下一行即返回为什么 PopIdle0 不带中断使能/关闭— 根据注释 “Note the HAL returns with interrupts on”IdleFunction返回时中断已经开启。HalProcessorIdle在执行hlt前通过_enable()开中断hlt后的隐式中断处理完成后控制流返回 IdleLoop 的while (TRUE)顶部重新走_enable()→YieldProcessor()→_disable()流程。与调度器的协作关系中断/异常 │ ▼ KiDispatchInterrupt ← 时钟中断、IPI 等 │ ├─ 选择新线程 → Prcb-NextThread NewThread ├─ 请求 DPC 软件中断 └─ 返回到被中断的线程也可能是空闲线程 │ ▼ (如果是空闲线程且 IRQL 降至 PASSIVE_LEVEL) KiIdleLoop 的下一条指令执行 → 发现 NextThread → 上下文切换调度器不会直接调用KiIdleLoop而是通过设置Prcb-NextThread来间接通知空闲线程进行切换。典型的唤醒路径设备中断 → ISR → 请求 DPC → 软件中断 → KiDispatchInterrupt → 线程被唤醒 → 插入就绪队列 → Prcb-NextThread NewThread → 返回到空闲线程 → KiIdleLoop 发现 NextThread → KiSwapContext第一次上下文切换从 KiIdleLoop 到 Phase1Initialization引导 CPU 的第一次KiSwapContext发生在KiIdleLoop() → Prcb-NextThread Phase1Initialization 线程 (由 KiInitializeKernel → ExpInitializeExecutive 创建) → KiSwapContext(APC_LEVEL, IdleThread) → 切换到 Phase1Initialization 内核栈 → ret → KiThreadStartup → PspSystemThreadStartup → Phase1Initialization()之后 Phase1 初始化线程完成所有初始化工作最终创建 SMSS.EXE而空闲线程继续在KiIdleLoop中循环随时准备切换到新的就绪线程。设计要点总结特性说明永不返回DECLSPEC_NORETURNwhile(TRUE)是 CPU 的最终归宿节能设计无工作时执行HLT指令暂停 CPU等待中断唤醒DPC 处理在空闲上下文中执行 DPC避免占用工作线程时间片中断窗口循环顶部短暂sti让挂起中断有机会执行竞态保护检查共享调度状态时cli关中断微架构优化PAUSE指令提示 Hyper-Threading / 流水线优化SMP 安全KiSwapContext在SYNCH_LEVEL执行#ifdef CONFIG_SMP

相关新闻

2026年7类热门职业证书官方报考指南:陪诊师 | 物业经理 | 人力资源管理师 | 心理咨询师 | 图书管理员 | 健康管理师 | 公共营养师全汇总

2026年7类热门职业证书官方报考指南:陪诊师 | 物业经理 | 人力资源管理师 | 心理咨询师 | 图书管理员 | 健康管理师 | 公共营养师全汇总

进入 2026 年,职业技能标准化建设持续推进,持证上岗逐步成为多行业的准入标配。从民生服务到企业管理,从健康领域到文化服务,各类职业证书的含金量与职场适配度不断提升。本文整理 7 类当下热度高、就业前景广的职业证书&#xff…

2026/10/25 9:36:34 阅读更多 →
从STM32到ESP32-S3:开源计算器移植实战

从STM32到ESP32-S3:开源计算器移植实战

1. 项目概述去年夏天,我在GitHub上偶然发现了NumWorks计算器的开源项目,这个基于STM32平台的图形计算器以其优雅的UI设计和完整的数学功能吸引了我。作为一名嵌入式开发者,我萌生了一个大胆的想法:能否将它移植到性能更强、价格更…

2026/10/25 16:11:42 阅读更多 →
2015年Android开发工具链与框架演进回顾

2015年Android开发工具链与框架演进回顾

1. 2015年Android开发生态全景回顾2015年是Android开发史上具有里程碑意义的一年。Material Design设计语言在经历2014年的发布后开始全面普及,Android Studio 1.0正式版发布取代Eclipse成为官方IDE,Gradle构建系统也日趋成熟。这一年涌现了大量优秀的开…

2026/10/26 11:48:17 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/10/25 11:19:54 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/10/25 22:36:10 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/26 4:52:12 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/10/25 10:02:42 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/10/26 5:00:37 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/10/26 3:16:46 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/25 10:02:43 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/25 13:21:54 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/26 8:34:37 阅读更多 →