Windows进程与线程学习笔记(六)—— 线程切换
主动切换
- 在上一篇中,分析了模拟线程切换:SwitchThread
- 在Windows中,也有类似的函数:KiSwapContext
分析KiSwapContext
查看405837处ECX的来源:KiSwapThread
分析SwapContext
分析KiSWapThread
查看交叉引用表,也就是有哪些函数调用了这个函数
再查看其中 KeWaitForSingleObject 的交叉引用
总结
- Windows中绝大部分API都调用了SwapContext这个函数,也就是说,只要调用了该函数,就会导致线程切换
- 线程切换时会比较是否属于同一个进程,如果不是,便切换Cr3,Cr3换了,进程也就切换了
思考:
- 如果不调用API,就可以一直占用CPU吗?
- 如果当前线程不去调用系统API,操作系统如何实现线程切换
时钟中断切换
中断一个正在执行的程序的方式:
- 异常:比如缺页,或者INT N指令
- 中断:比如时钟中断
系统时钟
- 在Windows操作系统当中,没个10~20毫秒便会触发一次时钟中断
- 如要获取当前的时钟间隔值,可使用Win32 API:GetSystemTimeAdjustment
执行流程:
分析INT 0x30
ALT+T定位IDT表
KiStartUnexpectedRange 跳到了另一个函数:KiUnexpectedInterruptTail
KiUnexpectedInterruptTail 调用了 HalBeginSystemInterrupt 和 HalEndSystemInterrupt
在导入表中查看这两个函数来源,都来自HAL.dll
分析HAL.dll
HalBeginSystemInterrupt:
HalEndSystemInterrupt:
KiDispatchInterrupt 又来自 ntoskrnl
最终,KiDispatchInterrupt 调用了 SwapContext
异常处理
- 如果一个线程不调用API,并且在代码中屏蔽中断(调用CLI指令),并且不会出现异常,那么当前线程将永久占有CPU
- 单核CPU占用率100%,2核CPU占用率50%
- Windows并非是“抢占式”操作系统,所谓的“抢“”必须是当前线程允许其它线程“抢”,否则是“抢”不到的