KeWaitForSingleObject简析

这个函数在进行同步操作时经常会用到,它内部的工作流程是什么样的呢?让我来试着分析分析吧. (以反编译的汇编代码片段为材料)

NTSTATUS KeWaitForSingleObject(
    IN PVOID  Object,//分发器对象(dispatcher object),像(event,mutex,semaphore,thread or timer)
    IN KWAIT_REASON  WaitReason,
    IN KPROCESSOR_MODE  WaitMode,
    IN BOOLEAN  Alertable,
    IN PLARGE_INTEGER  Timeout OPTIONAL
    );

The KeWaitForSingleObject routine puts the current thread into a wait state until the given dispatcher object is set to a signaled state or (optionally) until the wait times out.–(from ddk)
KeWaitForSingleObject例程将当前线程(ethread里包含几个以Wait开头的字段,有WaitIrql,WaitMode,WaitStatus)置为等待状态,直到提供的分发器对象被设置为已处理状态,或者第五个参数给出的时间Timeout走完。

8408ad4c 8b4518          mov     eax,dword ptr [ebp+18h];第五个参数
8408ad4f 53              push    ebx
8408ad50 56              push    esi
8408ad51 648b3524010000  mov     esi,dword ptr fs:[124h];--@1
8408ad58 0fba763c03      btr     dword ptr [esi+3Ch],3
8408ad5d 57              push    edi
8408ad5e 0f92c3          setb    bl
8408ad61 8944242c        mov     dword ptr [esp+2Ch],eax
8408ad65 8dbec0000000    lea     edi,[esi+0C0h];--@2
8408ad6b 84db            test    bl,bl
8408ad6d 7509            jne     nt!KeWaitForSingleObject+0x3c (8408ad78)

btr和setb指令???在@1处,fs寄存器总是指向kpcr(processor control region 处理器控制区),在偏移为0x120处是该结构的最后一个成员PrcbData,其类型为_kprcb;在结构_kprcb的0x0x4处是成员CurrentThread。在ethread结构的0x3c处成员MicsFlags记录了一些重要的状态信息(其实在kthread结构里)如下:

   +0x03c KernelStackResident : Pos 0, 1 Bit
   +0x03c ReadyTransition  : Pos 1, 1 Bit
   +0x03c ProcessReadyQueue : Pos 2, 1 Bit
   +0x03c WaitNext         : Pos 3, 1 Bit
   +0x03c SystemAffinityActive : Pos 4, 1 Bit
   +0x03c Alertable        : Pos 5, 1 Bit;是否可以'叫醒'
   +0x03c GdiFlushActive   : Pos 6, 1 Bit
   +0x03c UserStackWalkActive : Pos 7, 1 Bit
   +0x03c ApcInterruptRequest : Pos 8, 1 Bit;Apc 中断请求
   +0x03c ForceDeferSchedule : Pos 9, 1 Bit
   +0x03c QuantumEndMigrate : Pos 10, 1 Bit
   +0x03c UmsDirectedSwitchEnable : Pos 11, 1 Bit
   +0x03c TimerActive      : Pos 12, 1 Bit;是否使用计时器
   +0x03c SystemThread     : Pos 13, 1 Bit;是不是系统线程
   +0x03c Reserved         : Pos 14, 18 Bits
   +0x03c MiscFlags        : Int4B

接下来确定Irql是DpcLevel,为什么是这个级别呢?因为延迟过程调用(Dpc)和线程分发器运行于同一级别,并且在这个函数里发生了线程的切换需要线程分发器的帮助。(不确定,我没实验证实)

8408ad6f ff157c510184    call    dword ptr [nt!_imp__KeRaiseIrqlToDpcLevel (8401517c)]
8408ad75 88466a          mov     byte ptr [esi+6Ah],al;WaitIrql=al  
8408ad8d   and     dword ptr [esi+3Ch],0FFFFFFDFh;set Alretable to 0
8408ad     cmp     byte ptr [ebp+14h],0
8408ad     mov     cl,byte ptr [ebp+10h]
8408ad98   mov     eax,dword ptr [esi+3Ch]
8408ad9b   mov     byte ptr [esi+38h],0;WaitRegister->Flags=0
8408ad9f   mov     byte ptr [esi+6Bh],cl;WaitMode=第3个参数
8408ada2   je      nt!KeWaitForSingleObject+0x6e (8408adaa) 
 接着又是各种检查(痛苦)。 
8408adf5  cmp     byte ptr [esi+55h],dl;ApcStateFill[15]
8408adf8 je      nt!KeWaitForSingleObject+0xf3 (8408ae2f) 
 UCHR ApcStateFill[23] 表示的意义不了解。 对这个字符数组进行了大量操作。
8b4c2414        mov     ecx,dword ptr [esp+14h]
c6466805        mov     byte ptr [esi+68h],5;State=5
33c0            xor     eax,eax
f02101          lock and dword ptr [ecx],eax
8a450c          mov     al,byte ptr [ebp+0Ch];WaitReason
888687010000    mov     byte ptr [esi+187h],al
a180351484      mov     eax,dword ptr [nt!KeTickCount (84143580)]
898680000000    mov     dword ptr [esi+80h],eax
8b4518          mov     eax,dword ptr [ebp+18h];WaitTime
3bc2            cmp     eax,edx
0f84fc000000    je      nt!KeWaitForSingleObject+0x258 (8408af94)

到这里大概是所有反编译代码的1/6,后面的hold不住了,就简单的说一下吧。同步对象有事件,信号量,互斥体,计时器等,但在KeWaitForSingleObject 单独有一个参数 Timeout 表示一段时间,实际上在它的内部有大片的代码是和时间,计时器(Timer)有关,可见Timer的地位比较特殊。当等待的条件不满足时,当前线程就会处于等待状态,由KicommitThreadWait去完成此操作;当某个时候条件满足,KiExitThreadWait将会被调用使线程的状态恢复重新运行。根据不同的同步对象实际检查等待条件是否满足时处理也不一样。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值