线程链表与线程切换
Posted onetrainee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程链表与线程切换相关的知识,希望对你有一定的参考价值。
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html
线程链表与线程切换
1. 线程等待链表与调度链表
1)在XP操作系统上,其是全局变量
KiWaitListHead - 等待链表
比如:线程调用了Sleep()或者WaitForSingleObject()等函数,就挂到这个链表中。
KiDispatcherReadyListHead - 调度链表
其存在32个链表,按不同调度级别来进行划分。
操作系统所有线程:当前KCPR正在跑的+等待链表+32个调度链表。
2)Win7操作系统及以上
其调度链表与等待链表其存储于KPRCB中,而不是全局变量。
这里要注意,如果要遍历链表,则在高版本上搜索KPRCB中的有关属性。
2.线程切换的方式
1)创建一个进程的时候,其处于就绪状态;
2)时钟中断,或者系统调用API的时候,其他线程时间随便到了,或者主动休眠,让出CPU的权力,切换线程;
3)进入一个等待状态,堆栈内存换出到磁盘上;
4)线程的堆栈磁盘还如到内存;
5)换入完毕,然后在这个线程插入到就绪链表中,根据有限级别,找到对应的链表;
6)该线程就有一顶几率运行了。
3.进程切换逆向细节
其进程切换从 KiSwapThread->KiSwapContext->SwapContext函数依次递进,我们下面依次分析这几个函数。
1)KiSwapThread函数
可以看到,该函数的主要目的是找到就绪线程,先从KPCR中找,如果没有则调用函数KiFindReadyThread从就绪链表中找,如果仍没有找到则切换空闲线程跑。
2)KiSwapContext函数
可以看出该函数的主要目的是先将堆栈保存在寄存器中,之后准备好就绪线程和当前线程的_KTHREAD以及KPCR结构体。
3)SwapContext函数
该函数是线程切换的核心函数,该函数虽然看起来庞大,但是只要把握五点即可:
① esp的切换,其是线程切换的核心,只要将esp切换就能把线程的堆栈切换掉,实现整个线程工作环境的切换。
② 三环下TEB的切换,我们知道三环进零环FS由TEB切换到Thread,其原因是TEB存储在IDT[7]中,KPCR存储在IDT[6]中,即切换FS指向即可(可以用OD和windbg依次读取FS寄存器验证)。
③ 进程切换的同时会比较是否是同一线程,如果不是则完成线程的切换。
④ Esp0指向的是TrapFrame结构,其存储在TSS.Esp0中,三环进零环就是通过TSS寄存器来找到有关位置的。
⑤ 线程切换后会判断是否存在内核APC,如果有就去转去执行。
以上是关于线程链表与线程切换的主要内容,如果未能解决你的问题,请参考以下文章
EventBusEventBus 源码解析 ( 事件发送 | 发布线程为 子线程 切换到 主线程 执行订阅方法的过程分析 )