进程线程002 等待链表 调度链表

前言

进程结构体EPROCESS(0x50和0x190)是2个链表,里面圈着当前进程的所有线程。

对进程断链,程序可以正常运行,原因是CPU执行与调度是基于线程的,进程断链只是影响一些遍历系统进程的API,并不会影响程序执行。

对线程断链也一样,断链后在Windbg或者OD无法看到被断掉的线程,但并不影响线程执行。

等待链表

线程有三种状态:就绪 等待 运行。

当线程调用了Sleep或者WaitForSingleObject等函数时,就挂到这个链表上。用下面这条命令可以查看等待链表。

kd> dd KiWaitListHead

KiWaitListHead是一个全局变量,里面存的是一个双向链表。阻塞中的线程一定在这个等待链表里。这个双向链表指向KTHREAD这个结构体的下面这个位置。

kd> dt _KTHREAD
   +0x074 WaitListEntry    : _LIST_ENTRY
   +0x074 SwapListEntry    : _SINGLE_LIST_ENTRY

33个链表

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

这些链表都使用了KTHREAD(0x60)的位置,也就是说线程在某一时刻,只能属于其中一个圈。

调度链表

就绪链表也称为调度链表,既然有32个链表,就要有32个链表头。在windbg中用下面的命令查看调度链表

kd> dd KiDispatcherReadyListHead L70

KiDispatcherReadyListHead是一个全局变量,存储了32个链表的链表头。那么为什么等待链表只有1个,而调度链表有32个呢。原因在于运行中的线程是有线程优先级的,这32个链表里面存储的就是不同的优先级的线程。

版本差异

XP只有32个圈,也就是说上面这个数组只有一个,多核也只有一个。W7也是一样的只有一个圈。如果是64位,那就有64个圈。

服务器版本:KiWaitListHead整个系统只有一个,但KiDispatcherReadyListHead这个数组有几个CPU就有几组

总结

  1. 正在运行的线程在KPCR中
  2. 准备运行的线程在32个调度链表里,KiDispatcherReadyListHead是个数组存储了这32个链表头
  3. 等待状态的线程存储在等待链表里,KiWaitListHead存储链表头
    数组存储了这32个链表头
  4. 等待状态的线程存储在等待链表里,KiWaitListHead存储链表头
  5. 这些圈都挂在同一个相同的位置KTHREAD结构体
发布了99 篇原创文章 · 获赞 89 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_38474570/article/details/103792379