Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html
进程与线程
1. 线程的等待/调度链表
KiWaitListHead - 等待链表
比如:线程调用了Sleep()或者WaitForSingleObject()等函数,就挂到这个链表中。
KiDispatcherReadyListHead - 调度链表
其存在32个链表,按不同调度级别来进行划分。
操作系统所有线程:当前KCPR正在跑的+等待链表+32个调度链表。
2. 线程切换与TSS
1)内核栈的描述:
2)三环进零环方式
《系统调用》三环进零环时,其根据TSS段中的SS0,ESP0来找到零环的堆栈。
3)如何用一个TSS来保存所有线程的SP0
现在我们面临一个问题:各个线程都有自己的内核堆栈,但只有一个TSS,如何保存的呢?
答案:当发生切换时,其会切换不同线程的Esp0(SS0公用一个段选择子,不用切换)
1> 切换esp0
我们可以看到,开始从栈底拓展到0x210存储浮点寄存器。
2> 切换CR3
4)总结
1> 首先,pKPCR中保存着常用的结构,不要看到pKCRP->TSS就认为每一个CPU都存在一个TSS,TSS保存在任务段寄存器中。
2> TSS线程切换时只切换了两个:Esp0,CR3(当发现不是同一线程时)。
3. FS:[0]的切换
FS在三环时指向TEB,但在零环指向KPCR(地址固定是0FFDFF000h)。
FS是段描述符,其形式如下:
现在有两种方式:FS指向的段选择子改变;只改正段选择子的BaseAddress。
而Windows采用后面一种方式,即:无论在三环和零环,FS的段选择子是不会改变的(始终为7),而是直接修改GDT[7].BaseAddress地址。
因此 FS:[x],之前为TEB.x,进入零环之后为 KPCR.x,这样就很轻松实现切换。
原文:https://www.cnblogs.com/onetrainee/p/12602302.html