36 进程与线程之等待链表调度链表

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

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

    对线程断链也是一样的,断链后在Windbg或者OD中无法看到被断掉的线程,但并不影响其执行(仍然再跑)。
    
    1、33个链表

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

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

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

    2、等待链表

    kd> dd KiWaitListHead
    

kd> dd KiWaitListHead
80553d88  86212a88 8632a5a0 00000011 00000000
80553d98  e57a42bd d6bf94d5 01000013 ffdff980
80553da8  ffdff980 80500df0 00000000 000021f4
80553db8  00000000 ffdff9c0 80553dc0 80553dc0
80553dc8  00000000 00000000 80553dd0 80553dd0
80553dd8  00000000 00000000 00000000 863b0af0
80553de8  00000000 00000000 00040001 00000000
80553df8  863b0b60 863b0b60 00000001 00000000

(双向链表,两个值都有用,通过这个值可以遍历所有处于等待的线程,指向的是线程结构体ETHREAD)

    比如:线程调用了Sleep() 或者 WaitForSingleObject()等函数时,就挂到这个链表

   通过逆向系统代码可以追出KiWaitListHead这类的全局符号

    通过以下方式找到所属进程(一直等待链表的一个值为0x86212a88),可以

dt  _ETHREAD 86212a88-60---->查看0x220位置进程结构体指针 a

dt _EPROCESS a--->0x174地址得到进程名

kd> dd KiWaitListHead
kd> dt _KTHREAD 895fd230(表里成员) - 60
kd> dt _ETHREAD 895fd230(表里成员) - 60

_ETHREAD->0x220 ThreadsProcess   : 0x898ac6b8 _EPROCESS

kd> dt _EPROCESS 0x898ac6b8

 

3、调度链表(就绪链表)

    调度链表有32个圈,就是优先级:0 - 31  0最低  31最高  默认优先级一般是8

    改变优先级就是从一个圈里面卸下来挂到另外一个圈上

    这32个圈是正在调度中的线程:包括正在运行的和准备运行的

    比如:只有一个CPU但有10个线程在运行,那么某一时刻,正在运行的线程在KPCR中,其他9个在这32个圈中
    
    4、查看调度链表

    既然有32个双向链表,就要有32个链表头。

    kd> dd KiDispatcherReadyListHead L70

kd> dd KiDispatcherReadyListHead L70
80554820  80554820 80554820 80554828 80554828
80554830  80554830 80554830 80554838 80554838
80554840  80554840 80554840 80554848 80554848
80554850  80554850 80554850 80554858 80554858
80554860  80554860 80554860 80554868 80554868
80554870  80554870 80554870 80554878 80554878
80554880  80554880 80554880 80554888 80554888
80554890  80554890 80554890 80554898 80554898
805548a0  805548a0 805548a0 805548a8 805548a8
805548b0  805548b0 805548b0 805548b8 805548b8
805548c0  805548c0 805548c0 805548c8 805548c8
805548d0  805548d0 805548d0 805548d8 805548d8
805548e0  805548e0 805548e0 805548e8 805548e8
805548f0  805548f0 805548f0 805548f8 805548f8
80554900  80554900 80554900 80554908 80554908
80554910  80554910 80554910 80554918 80554918
80554920  00000000 00000000 00000000 00000000
80554930  00000000 00000000 00000000 00000000
80554940  00000000 00000000 00000000 00000000
80554950  00000000 e1006000 00000000 00000000
80554960  00000001 ee25cc90 00000000 00040001
80554970  00000000 80554974 80554974 00000000
80554980  00000000 863ea3d0 863ea5a0 00000000
80554990  00000000 00000000 00000000 00000000
805549a0  00b19001 00000000 00b1a001 00000000
805549b0  00b1b001 00000000 00b1c001 00000000
805549c0  f7c0b300 000d0069 00000000 00000010
805549d0  00000000 00000000 00000000 00000000


    
    5、版本差异

    XP只有一个33个圈,也就是说上面这个数组只有一个,多核也只有一个.

    Win7也是一样的只有一个圈,如果是64位的,那就有64个圈.

    服务器版本:

        KiWaitListHead整个系统只有一个,但KiDispatcherReadyListHead这个数组有几个CPU就有几组

    6、总结:

    1、正在运行的线程在KPCR中

    2、准备运行的线程在32个调度链表中(0 - 31级),KiDispatcherReadyListHead 是个数组存储了这32个链表头.

    3、等待状态的线程存储在等待链表中,KiWaitListHead存储链表头.

    4、这些圈都挂一个相同的位置:_KTHREAD(0x060),无论线程处于等待状态和调度状态,指针都挂在0x60位置
 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值