07 线程切换

线程切换时会比较是否属于同一个进程,如果不是,切换Cr3,Cr3换了,进程也就切换了

时钟中断

绝大部分系统内核函数都会调用SwapContext函数,来实现线程的切换,那么这种切换是线程主动调用的。那如果当前的线程不去调用系统API,操作系统如何实现线程切换呢?那就靠时钟中断了,这个是被动切换。可以通过中断和异常来实现中断一个正在执行的程序。其中,时钟中断也是一种中断,中断号0x30
如果一个线程不调用API,在代码中屏蔽中断(CLI指令),并且不会出现异常,那么当前线程将永久占有CPU

时间片管理

时钟中断会导致线程进行切换,但并不是说只要有时钟中断就一定会切换线程,时钟中断时,如下两种情况会导致线程切换:

  • 当前的线程CPU时间片到期
  • 有备用线程:KPCR.PrcbData.NextThread

时间片

  • 当一个新的线程开始执行时,初始化程序会在_KTHREAD.Quantum赋初始值,该值的大小由_KPROCESS.ThreadQuantum决定
  • 每次时钟中断会调用KeUpdateRunTime函数,该函数每次将当前线程Quantum减少3个单位,如果减到0,则将KPCR.PrcbData.QuantumEnd的值设置为非0
  • KiDispatchInterrupt判断时间片到期,调用KiQuantumEnd重新设置时间片、找到要运行的线程

存在备用线程

这个值被设置时,即使当前线程的CPU时间片没有到期,仍然会被切换

在这里插入图片描述

FS

FS:[0]寄存器在3环时指向TEB,进入0环后FS:[0]指向KPCR。系统中同时存在很多个线程,这就意味着FS:[0]在3环时指向的TEB要有多个,即每个线程一份。但在实际的使用中我们发现,当我们在3环查看不同线程的FS寄存器时,FS的段选择子都是相同的,那是如何实现通过一个FS寄存器指向多个TEB呢?这一切的一切都在SwapContext这个函数里面

线程优先级

之前讲过有三种情况会导致线程切换,在KiSwapThread与KiQuantumEnd函数中都是通过KiFindReadyThread来找下一个要切换的线程,KiFindReadyThread是根据什么条件来选择下一个要执行的线程呢?

调度链表有32个,每次都从头开始查找效率太低,所以Windows都过一个DWORD类型变量的变量来记录,正好是32位,一个位代表一个链表,当向调度链表.中挂入或者摘除某个线程时,会判断当前级别的链表是否为空,为空将.变量对应位置0,否则置1,这个变量就是==_kiReadySummary==。

多CPU会随机寻找KiDispatcherReadyListHead(调度链表)指向的数组中的线程,线程可以绑定某个CPU,可以使用API:SetThreadAffinityMask进行设置。

如果没有就绪线程怎么办?CPU是不可能闲下来的,它会执行一个空闲线程,即为IdleThread

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值