28.Windows线程切换之主动切换(KiSwapThread)

Posted KernelHack

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了28.Windows线程切换之主动切换(KiSwapThread)相关的知识,希望对你有一定的参考价值。

目录

前言

调用API触发线程切换机制

KiSwapThread

参数分析

函数功能

KiSwapContext

SwapContext


前言

  • 通过研究KiSwapThread函数,就可以知道单核CPU是如何同时运行多个进程.
  • 需要了解进程内核结构KPROCESS,其成员CR3,ApcState等等.
  • 需要了解线程内核结构KTHREAD,会用到很多线程内核结构成员.并且对WindowsAPI调用有了解(系统调用),需要了解一个API是如何进R0,以及如何从R3堆栈切换到R0堆栈等.
  • 需要了解处理器控制区KPCR,线程切换会通过其成员ReadySummary / DisPatcherReadyListHead来查找当前核就绪线程等.
  • 建议阅读此文前先查看模拟Windows线程切换,Windows查找就绪线程.

调用API触发线程切换机制

IDA查看函数KiSwapThread.

通过交叉引用查看哪些函数调用了线程切换函数.

通过交叉引用查看哪些函数调用了KiCommitThreadWait

通过KeWaitForSingleObject函数交叉引用可以看出,大部分API调用时最终会触发线程切换.

分析可以得出结论:Windows中绝大部分API最终都会调用了KiSwapThread(SwapContext后文详解)函数,也就意味着调用API相当于主动切换线程.

KiSwapThread

参数分析

通过交叉引用查看调用函数KiCommitThreadWait传递了哪些参数.

使用ECX,DEX传参可以得出调用约定为FASTCALL.

参数EDX来源于EBX,EBX函数上方赋值后指向_KPRCB

参数ECX来源于EDI,EDI为当前函数参数1(KTHREAD)

参考WRK定义

LONG_PTR
FASTCALL
KiSwapThread (
    IN PKTHREAD OldThread, //当前线程
    IN PKPRCB CurrentPrcb //当前核KPRCB
    );

函数功能

线程切换KiSwapThread函数在不同版本系统下实现都有略微差异.只研究核心代码.

发现其实现中调用了KiSearchForNewThread函数.

分析得知函数首先直接获取_KPRCB结构中NextThread,如果此值不为空,将NextThread设置为0,并且把取出线程设置为KPRCB.CurrentThread,线程KTHREAD.State设置为2后直接返回该线程结构.

如果_KPRCB结构中NextThread为空,通过KiSelectReadyThread函数继续查找,该函数实现为直接查找指定优先级的线程,如果找到线程设置对应状态后返回.

如果KiSelectReadyThread函数也没找到,会执行KiFindReadyThread函数,通过KPRCB -> ReadySummary就绪位图循环查找符合执行条件的线程设置对应状态后返回.

KiSearchForNewThread函数首先判断是否找到就绪线程,找到跳转(这里按照成功路线分析).

取出线程不是IdleThread且不为当前线程,同时处于未运行状态会跳转.

线程查询校验全部完毕后最终跳转此处(EDX为要切换线程,ECX为当前线程),执行函数KiSwapContext.

KiSwapContext

函数并未做任何功能实现,而是初始化参数后调用SwapContext函数

SwapContext

函数入口会循环(自旋)判断要执行线程运行状态,直到未运行时跳出.

线程状态检测跳转后,会进行时间与浮点相关初始化,并且会将当前线程异常处理链表保存到堆栈中.

初始化工作结束后,开始切换堆栈(相当于切换线程(模拟线程中有详细介绍)),并且判断当前线程所属进程来决定是否需要切换CR3.至此实际上已经完成线程切换.

两个线程对应堆栈图如下:

系统调用分析中说过TSS.ESP0永远存储当前线程_KTRAP_FRAME,论证如下

内核堆栈结构以及通过_KTHREAD -> 堆栈相关回溯ESP0,获得_TRAP_FRAME:

段寄存器相关文章中提起,x86中未使用GS段寄存器,线程切换就会清空GS值,论证如下:

在介绍段寄存器说FS寄存器在R3时指向当前线程TEB,论证如下:

线程主动切换分析完毕,按照大致流程以及对段,TSS,_KTRAP_FRAME补充.这里再次说明,参考WRK, Windows内核原理与实现, Windows内核情景分析时不要完全按照它们的内容进行比较,对自己内核文件进行分析最为准确.同时要搞懂全部实现比较难,按照主线路分析即可.

当前内核文件MSDN搜索cn_windows_7_professional_with_sp1_x86_dvd_u_677162.iso

以上是关于28.Windows线程切换之主动切换(KiSwapThread)的主要内容,如果未能解决你的问题,请参考以下文章

当前线程阻塞时,操作系统可以主动切换到另一个线程吗?如果是这样,是不是会使异步编程的价值小得多?

RxJava2探索-线程切换原理之observeOn

RxJava2探索-线程切换原理之observeOn

java线程调度

27.Windows线程切换之线程查找(KiFindReadyThread)

操作系统之用户级线程