11.Windows线程切换_线程优先级

(1)、当前线程主动调用API:
API函数->KiSwapThread->KiSwapContext->SwapContexti

(2)、当前线程时间片到期:
KiDispatchInterrupt->KiQuantumEnd->SwapContext

(3)、有备用线程(KPCR.PrcbData.NextThread)
KiDispatchInterrupt->SwapContext

在KiSwapThread与KiQuantumEnd函数中都是通过KiFindReadyThread来找下一个要切换的线程, KiFindReadyThread是根据什么条件来选择下一个要执行的线程呢?

调度链表(32个)

kd> dd KiDispatcherReadyListHead
80554820  80554820 80554820 80554828 80554828
80554830  80554830 80554830 80554838 80554838
80554840  80554840 80554840 80554848 80554848
80554850  80554850 80554850 80554858 80554858
80554860  80554860 80554860 80554868 80554868
80554870  80554870 80554870 80554878 80554878
80554880  80554880 80554880 80554888 80554888
80554890  80554890 80554890 80554898 80554898

KiFindReadyThread查找方式:
按照优先级别进行查找: 31…30…29…28…

也就是说,在本次查找中,如果级别31的链表里面有线程,那么就不会查找级别为30的链表!

如何高效查找

调度链表有32个,每次都从头开始查找效率太低,所以Windows都过一个 DWORD类型变量的变量来记录:

当向调度链表(32个)中挂入或者摘除某个线程时,会判断当前级别的链表是否为空,为空将DWORD变量对应位置0,否则置1。

.如下图:
在这里插入图片描述
第30位与28位是有等待调度的线程的,这个变量:_kiReadySummary

向等待链表挂入或者删除,它是根据判断链表中两个的成员是否一样且是否与当前的地址相同来判断它是否为空,如果两成员一样并且不等于当前地址说明这两个中有一个等待调度的线程

多cpu会随机寻找KiDispatcherReadyListHead指向的数组中的线程。线程可以绑定某个cpu (使用api: setThreadAffinityMask)

如果没有就绪线程怎么办
PrcbData:
+0x004 CurrentThread : Ptr32 KTHREAD //当前线程
+0x008 NextThread : Ptr32 KTHREAD //备用线程
+0x00C IdleThread :Ptr32 KTHREAD //空闲线程

如果cpu里没有等待调度的线程它就会跑IdleThread这条线程,每一个KPCR里都会指定一个空闲线程。

11.Windows线程切换_线程优先级_第1张图片

11.Windows线程切换_线程优先级_第2张图片

11.Windows线程切换_线程优先级_第3张图片

CPU一但开始就不能停,就算没有等待调度的线程,也要执行空闲线程。

你可能感兴趣的:(进程与线程)