线程被动切换(时间碎片) - KiReadyThread函数详细分析

Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html

线程被动切换(时间碎片) - KiReadyThread函数详细分析

每个线程都存在自己的时间碎片(_KTHREAD+0x6f QuanTum),当时间到了之后,其会让其他线程运行,现在我们就来详细分析一下其有关细节。

 

时间片更新函数:

HalpHpetClockInterrupt->KeUpdateSystemTime->KeUpdateRunTime

时间片检查函数:

HalEndSystemInterrupt->KiDispatchInterrupt

 

时间更新是利用CPU的DPC机制,所谓DPC就是类似于看门狗,CPU运行一定时间就会调用DPC运行某个DPC函数,之后我们再来详细分析DPC这块的内容。

 

1)_KiDispatchInterrupt 函数分析

  时钟中断最后会调用 _KiDispatchInterrupt 这个函数,该函数思路比较清晰,判断时间碎片等有关函数。

  其中关键的说Windows是采用抢占模式的其实就看一行代码:

  “②”中如果其不存在下一个线程 KPCR.NextThread,其并不会去主动去找,而是继续运行原来线程,所以是主动抢占式的;其不存在一个队列,每个线程有序运行。

  操作系统就看一个KPCR.NextThread,如果该值为空就继续运行原来的线程。

  

 

2)_KiReadyThread 函数分析

  该函数是对于原来老的线程的处理,通过分析它你可以清楚地理解线程切换更详细的过程,但同时其也做了很多额外工作,比如线程的进程不在内存中,其会映射进内存。

  我们应该分析其主干,对于涉及的额外的工作,我们并不要花过多精力去分析,这一点我们首先是要明确的。

  (1)其先找到合适的CPU,在我们单核情况下其就存在单独一个CPU;

  (2)判断CPU的 KPRCB.NextThread是否为空:

    当为空时:

      ① 判断当前线程优先级和老的线程优先级的大小;

      ② 如果老的线程优先级比较大,则直接放入KPCR.NextThread中;否则放入线程的等待队列中 - KThread.WaitListEntry中

      ③ 其中老线程是被抢占的(preemted),则放入 KThread.WaitListEntry头部,作为补偿,否则放入尾部。

    当不为空时:

      ① 比较NextThread和老线程的优先级大小;

      ② 如果老的线程比较大,则放入KPCR.NextThread,而原来的老线程会设置有关标志位再去找自己合适的位置。

      ③ 否则放入线程的等待队列中 - KThread.WaitListEntry中其中老线程是被抢占的(preemted),则放入 KThread.WaitListEntry头部,作为补偿,否则放入尾部。

  注释:在分析中会涉及到大量的进程与线程状态转换,我们从WRK中找到下列的有关定义,结合这个能帮助我们的理解。

  

 

3)_KiReadyThread 函数分析逆向细节

  这函数分支比较庞大,我们在这里就按照上面所说的,简要的画出其步骤流程图,很多地方已经加了注释,比较好理解的。

posted @ 2020-04-22 21:10  OneTrainee  阅读(896)  评论(0编辑  收藏  举报