线程切换的几种条件
如果学过操作系统,那么很容易就知道会有以下方法
- 时间片用完
- 强制切换
- 异常处理
时间片切换
其实也叫轮转调度算法,顾名思义当时间到达一定的时候,就会切换一个线程,接着运行,这样就可以让我们感受到我们的只有单核使用的程序却没有断过。
而在Windows中,当时间片到达时候,会引起中断异常也就是0x30
Windows系列操作系统的时间片一般为:10-20毫秒
如果要获取当前的时钟间隔值,可以使用:GetSystemTimeAdjustment
时钟中断的执行流程
主动切换
主要是KiSwapContext函数进行的
这里我在上一篇文章有逆向分析就不说了
线程切换TSS
在上一篇文章中,我们分析了KiSwapContext,所以我会直接说结论
线程切换的本质就是堆栈的切换,而新线程的堆栈存放_KTHREAD结构体中
而且我们知道,在SwapContext函数里,esp会减少0x210,而这0x210存放的是浮点寄存器的值,其上面就是我们熟悉的_Trap_Frame结构了
但是Windows和linux都没有使用这个东西,而是采用的堆栈来保存线程的各种寄存器的值
fs切换
由于fs在0环指向的是KPCR,3环指向的是TEB,所以FS也会切换,如何切换看我上一篇文章
优先级切换
上面我们提到有3种情况会导致线程切换:
那么,上一篇文章我也有说KiFindReadThread是用来找到下一个要执行的线程的,那么是根据什么条件查找呢?
KiFindReadThread查找条件
由于有32个调度链表和1个空闲链表,KiFindReadyThread的查找方式是按照优先级来进行查找的:31...28....20..0
也就是有级别高的线程就直接指向级别高的了,就不会再去找级别低的了
如何让查找效率变高?
如果没有就绪线程怎么办?
就会去空闲队列中查找