Windows进程与线程学习笔记(四)—— 等待链表&调度链表
前言
一、学习自
滴水编程达人
中级班课程,官网:https://bcdaren.com
二、海东老师牛逼!
要点回顾
- 进程结构体 _EPROCESS +0x050 和 _EPROCESS +0x190 这2个链表圈着当前进程所有的线程
- 对进程断链,程序可以正常运行,原因是CPU执行与调度是基于线程的,进程断链只是影响一些遍历系统进程的API,并不会影响程序执行
- 对线程断链也是一样的,断链后在Windbg或者OD中无法看到被断掉的线程,但并不影响其执行(线程仍然在跑)
33个链表
- 线程有3种状态:就绪、等待、运行
- 正在运行中的线程存储在KPCR中,就绪和等待的线程全在另外的33个链表中:
1个等待链表,32个就绪链表 - 等待链表和调度链表都使用了 _KTHREAD +0x060 这个位置,也就是说,线程在某一时刻,只能属于其中一个圈
等待链表
描述:
- 等待链表是一个双向链表
- 它有两个成员,一个向后遍历,一个向前遍历
- 当线程调用了Sleep() 或者 WaitForSingleObject()等函数时,就挂到这个链表(查看等待线程)
在WinDbg中查看:
kd>dd KiWaitListHead
kd>dt _KTHREAD
实验:分析等待链表中的线程所属的进程
第一步:查看所属线程结构体:
第二步:查看所属进程结构体
调度链表
描述:
- 调度链表共有32个双向链表
- 线程在调度链表的中下标表示线程级别(0~31)
- 在XP中,调度链表共有32个圈;在64位操作系统(如win7 64位)中,调度链表共有64个圈
- 在单核CPU操作系统中,无论是XP还是win7,都只有一组调度链表
- 但是在服务器版本系统中:等待链表只有一个,调度链表的数量等于CPU的数量
在WinDbg中查看:
dd KiDispatcherReadyListHead L70
总结
- 线程总数 = 1个等待链表 + 调度链表数量*CPU数量 + 1个正在运行的线程
- 无论是等待链表还是调度链表,在线程结构体中都位于 _KTHREAD +0x060 这个位置