avatar

Catalog
等待链表&调度链表

在前面介绍进程结构体时,进行了断链实验,程序可以正常运行,原因是CPU执行与调度的单位是线程,因此进程的断链并不影响程序的正常执行。对线程的断链也是一样的,断链后虽然可以隐藏断掉的线程,但同样不影响程序的执行。这说明,CPU调度时根本没有用到ThreadListEntry这个链表。接下来介绍两个与调度相关的链表:等待链表&调度链表

33个链表

  • 线程有3种状态:就绪、等待、运行

  • 正在运行中的线程存储在KPCR中,就绪和等待的线程全在另外的33个链表中。包括1个等待链表,32个就绪链表

  • 这些链表都使用了_KTHREAD+0x060这个位置(如果是Win7的话,位于KTHREAD+0x074的位置),也就是说,线程在某一时刻,只能属于其中一个链表内

等待链表

  • 查询指令:dd KiWaitListHead

  • 说明:

    • 等待链表是一个双向链表
    • 当线程调用了Sleep()或者WaitForSingleObject()等函数时,就挂到这个链表
  • 结构图:

  • 关系梳理:KiWaitListHead -> WaitListEntry(KTHREAD+0x60) -> ThreadProcess(ETHREAD+0x220) -> EPROCESS

调度链表

  • 查询指令:dd KiDispatcherReadyListHead L70
  • 说明:
    • 调度链表共32个双向链表
    • 有32个调度链表的原因是,运行中的线程是有线程优先级,根据下标表示线程优先级别(0~31)
    • 32位系统中,调度链表有32个(一组),64位系统则有64个(一组)
    • 普通操作系统,只有一组调度链表,服务器版本系统中,调度链表的数量等于CPU的数量,但等待链表只有一个
  • 结构图:

总结

  1. 正在运行的线程位于KPCR
  2. 准备运行的线程根据线程优先级的不同,分布在32个调度链表中; KiDispatcherReadyListHead是个数组,存储了32个链表头
  3. 等待状态的线程存储在等待链表里,KiWaitListHead存储了链表头
  4. 这些圈均挂在KTHREAD+0x060的位置(XP系统)
Author: cataLoc
Link: http://cata1oc.github.io/2020/03/30/%E7%AD%89%E5%BE%85%E9%93%BE%E8%A1%A8-%E8%B0%83%E5%BA%A6%E9%93%BE%E8%A1%A8/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶