news 2026/3/31 23:59:47

nt!KiDispatchInterrupt函数中nt!KiQueueReadyThread和nt!SwapContext和KiQuantumEnd3个函数的关系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
nt!KiDispatchInterrupt函数中nt!KiQueueReadyThread和nt!SwapContext和KiQuantumEnd3个函数的关系

nt!KiDispatchInterrupt函数中nt!KiQueueReadyThread和nt!SwapContext和KiQuantumEnd3个函数的关系

align 16
cPublicProc _KiDispatchInterrupt ,0
cPublicFpo 0, 0

mov ebx, PCR[PcSelfPcr] ; get address of PCR


。。。

;
; Check to determine if quantum end is requested.
;
; N.B. If a new thread is selected as a result of processing the quantum
; end request, then the new thread is returned with the dispatcher
; database locked. Otherwise, NULL is returned with the dispatcher
; database unlocked.
;

kdi40: sti ; enable interrupts
cmp byte ptr [ebx].PcPrcbData.PbQuantumEnd, 0 ; quantum end requested
jne kdi90 ; if neq, quantum end request

;
; Check to determine if a new thread has been selected for execution on this
; processor.
;

cmp dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; check if next thread
je kdi70 ; if eq, then no new thread

;
; N.B. The following registers MUST be saved such that ebp is saved last.
; This is done so the debugger can find the saved ebp for a thread
; that is not currently in the running state.
;
sub esp, 3*4
mov [esp+8], esi ; save registers
mov [esp+4], edi ;
mov [esp+0], ebp ;
mov edi, [ebx].PcPrcbData.PbCurrentThread ; get current thread address (as old thread)

;
; Raise IRQL to SYNCH level, set context swap busy for the old thread, and
; acquire the current PRCB lock.
;

ifndef NT_UP

call dword ptr [__imp__KeRaiseIrqlToSynchLevel@0] ; raise IRQL to SYNCH
mov byte ptr [edi].ThSwapBusy, 1 ; set context swap busy
lea ecx, [ebx].PcPrcbData.PbPrcbLock ; get PRCB lock address
lock bts dword ptr [ecx], 0 ; try to acquire PRCB lock
jnc short kdi50 ; if nc, PRCB lock acquired
fstCall KefAcquireSpinLockAtDpcLevel ; acquire current PRCB lock

endif

;
; Get the next thread address, set the thread state to running, queue the old
; running thread, and swap context to the next thread.
;

kdi50: mov esi, [ebx].PcPrcbData.PbNextThread ; get next thread address
and dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; clear next thread address
mov [ebx].PcPrcbData.PbCurrentThread, esi ; set current thread address
mov byte ptr [esi]+ThState, Running ; set thread state to running
mov byte ptr [edi].ThWaitReason, WrDispatchInt ; set wait reason
mov ecx, edi ; set address of curent thread
lea edx, [ebx].PcPrcbData ; set address of PRCB
fstCall KiQueueReadyThread ; ready thread for execution
CAPSTART <_KiDispatchInterrupt,SwapContext>
mov cl, APC_LEVEL ; set APC interrupt bypass disable
call SwapContext ; swap context

。。。

;
; Process quantum end event.
;
; N.B. If the quantum end code returns a NULL value, then no next thread
; has been selected for execution. Otherwise, a next thread has been
; selected and the source thread lock has been acquired.
;

kdi90: mov byte ptr [ebx].PcPrcbData.PbQuantumEnd, 0 ; clear quantum end indicator
CAPSTART <_KiDispatchInterrupt,_KiQuantumEnd@0>
stdCall _KiQuantumEnd ; process quantum end
CAPEND <_KiDispatchInterrupt>
stdRET _KiDispatchInterrupt ; return

第二部分:

VOID
KiQuantumEnd (
VOID
)
Routine Description:

This function is called when a quantum end event occurs on the current
processor. Its function is to determine whether the thread priority should
be decremented and whether a redispatch of the processor should occur.
当当前处理器上发生量子结束事件时,会调用此函数。
它的功能是确定是否应该降低线程优先级,以及是否应该重新分配处理器。

VOID
FASTCALL
KiQueueReadyThread (
IN PKTHREAD Thread,
IN PKPRCB Prcb
)
{

KxQueueReadyThread(Thread, Prcb);
return;
}


FORCEINLINE
VOID
KxQueueReadyThread (
IN PKTHREAD Thread,
IN PKPRCB Prcb
)

{

BOOLEAN Preempted;
KPRIORITY Priority;

ASSERT(Prcb == KeGetCurrentPrcb());
ASSERT(Thread->State == Running);
ASSERT(Thread->NextProcessor == Prcb->Number);

//
// If the thread can run on the specified processor, then insert the
// thread in the appropriate dispatcher ready queue for the specified
// processor and release the specified PRCB lock. Otherwise, release
// the specified PRCB lock and ready the thread for execution.
//

#if !defined(NT_UP)

if ((Thread->Affinity & Prcb->SetMember) != 0) {

#endif

Thread->State = Ready;
Preempted = Thread->Preempted;
Thread->Preempted = FALSE;
Thread->WaitTime = KiQueryLowTickCount();
Priority = Thread->Priority;

ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));

if (Preempted != FALSE) {
InsertHeadList(&Prcb->DispatcherReadyListHead[Priority],
&Thread->WaitListEntry);

} else {
InsertTailList(&Prcb->DispatcherReadyListHead[Priority],
&Thread->WaitListEntry);
}

Prcb->ReadySummary |= PRIORITY_MASK(Priority);

ASSERT(Priority == Thread->Priority);

KiReleasePrcbLock(Prcb);

#if !defined(NT_UP)

} else {
Thread->State = DeferredReady;
Thread->DeferredProcessor = Prcb->Number;
KiReleasePrcbLock(Prcb);
KiDeferredReadyThread(Thread);
}

#endif

return;
}

第三部分:

如果[ebx].PcPrcbData.PbNextThread=0则跳转到
kdi70: stdRET _KiDispatchInterrupt ; return
结束了,如果不为0则进行线程切换,
所以PcPrcbData.PbNextThread得真正含义是等待当前线程时间片用完就切换到NextThread

要切换到NextThread,需要两个条件,第一个是时间片用完,第二个是NextThread已经被选出来了。

;
; Check to determine if a new thread has been selected for execution on this
; processor.
;

cmp dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; check if next thread
je kdi70 ; if eq, then no new thread

;
; N.B. The following registers MUST be saved such that ebp is saved last.
; This is done so the debugger can find the saved ebp for a thread
; that is not currently in the running state.
;

.fpo (0, 0, 0, 3, 1, 0)

sub esp, 3*4
mov [esp+8], esi ; save registers
mov [esp+4], edi ;
mov [esp+0], ebp ;
mov edi, [ebx].PcPrcbData.PbCurrentThread ; get current thread address (as old thread)

;
; Raise IRQL to SYNCH level, set context swap busy for the old thread, and
; acquire the current PRCB lock.
;

ifndef NT_UP

call dword ptr [__imp__KeRaiseIrqlToSynchLevel@0] ; raise IRQL to SYNCH
mov byte ptr [edi].ThSwapBusy, 1 ; set context swap busy
lea ecx, [ebx].PcPrcbData.PbPrcbLock ; get PRCB lock address
lock bts dword ptr [ecx], 0 ; try to acquire PRCB lock
jnc short kdi50 ; if nc, PRCB lock acquired
fstCall KefAcquireSpinLockAtDpcLevel ; acquire current PRCB lock

endif

;
; Get the next thread address, set the thread state to running, queue the old
; running thread, and swap context to the next thread.
;

kdi50: mov esi, [ebx].PcPrcbData.PbNextThread ; get next thread address
and dword ptr [ebx].PcPrcbData.PbNextThread, 0 ; clear next thread address
mov [ebx].PcPrcbData.PbCurrentThread, esi ; set current thread address
mov byte ptr [esi]+ThState, Running ; set thread state to running
mov byte ptr [edi].ThWaitReason, WrDispatchInt ; set wait reason
mov ecx, edi ; set address of curent thread
lea edx, [ebx].PcPrcbData ; set address of PRCB
fstCall KiQueueReadyThread ; ready thread for execution
CAPSTART <_KiDispatchInterrupt,SwapContext>
mov cl, APC_LEVEL ; set APC interrupt bypass disable
call SwapContext ; swap context
CAPEND <_KiDispatchInterrupt>
mov ebp, [esp+0] ; restore registers
mov edi, [esp+4] ;
mov esi, [esp+8] ;
add esp, 3*4
kdi70: stdRET _KiDispatchInterrupt ; return

第四部分:

1: kd> g
Breakpoint 14 hit
eax=00000041 ebx=f78e6d48 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00720 esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
nt!KiDispatchInterrupt:
80b00720 648b1d1c000000 mov ebx,dword ptr fs:[1Ch] fs:0030:0000001c=f7737000
1: kd> x nt!KiQueueReadyThread
80a4412e nt!KiQueueReadyThread (struct _KTHREAD *, struct _KPRCB *)
1: kd> bp nt!KiQueueReadyThread
breakpoint 38 redefined
1: kd> dx -id 0,0,8954e020 -r1 ((ntkrnlmp!_KPRCB *)0xf7737120)
((ntkrnlmp!_KPRCB *)0xf7737120) : 0xf7737120 [Type: _KPRCB *]
[+0x000] MinorVersion : 0x1 [Type: unsigned short]
[+0x002] MajorVersion : 0x1 [Type: unsigned short]
[+0x004] CurrentThread : 0x8999d620 [Type: _KTHREAD *]
[+0x008] NextThread : 0x0 [Type: _KTHREAD *]

[+0x928] ReadySummary : 0x0 [Type: unsigned long]
[+0x92c] SelectNextLast : 0x0 [Type: unsigned long]
[+0x930] DispatcherReadyListHead [Type: _LIST_ENTRY [32]]
[+0xa30] DeferredReadyListHead [Type: _SINGLE_LIST_ENTRY]

1: kd> dx -id 0,0,8954e020 -r1 (*((ntkrnlmp!_KDPC_DATA (*)[2])0xf7737980))
(*((ntkrnlmp!_KDPC_DATA (*)[2])0xf7737980)) [Type: _KDPC_DATA [2]]
[0] [Type: _KDPC_DATA]
[1] [Type: _KDPC_DATA]
1: kd> dx -id 0,0,8954e020 -r1 (*((ntkrnlmp!_KDPC_DATA *)0xf7737980))
(*((ntkrnlmp!_KDPC_DATA *)0xf7737980)) [Type: _KDPC_DATA]
[+0x000] DpcListHead [Type: _LIST_ENTRY]
[+0x008] DpcLock : 0x0 [Type: unsigned long]
[+0x00c] DpcQueueDepth : 0x0 [Type: unsigned long]
[+0x010] DpcCount : 0xbb6 [Type: unsigned long]
1: kd> dx -id 0,0,8954e020 -r1 (*((ntkrnlmp!_SINGLE_LIST_ENTRY *)0xf7737b50))
(*((ntkrnlmp!_SINGLE_LIST_ENTRY *)0xf7737b50)) [Type: _SINGLE_LIST_ENTRY]
[+0x000] Next : 0x0 [Type: _SINGLE_LIST_ENTRY *]

1: kd> p
eax=00000041 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00727 esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
nt!KiDispatchInterrupt+0x7:
80b00727 fa cli
1: kd> !irql
Debugger saved IRQL for processor 0x1 -- 2 (DISPATCH_LEVEL)
1: kd> p
eax=00000041 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00728 esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up di pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046
nt!KiDispatchInterrupt+0x8:
80b00728 8b838c090000 mov eax,dword ptr [ebx+98Ch] ds:0023:f773798c=00000000
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0072e esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up di pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046
nt!KiDispatchInterrupt+0xe:
80b0072e 0b83c8090000 or eax,dword ptr [ebx+9C8h] ds:0023:f77379c8=00000000
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00734 esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up di pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046
nt!KiDispatchInterrupt+0x14:
80b00734 0b83500b0000 or eax,dword ptr [ebx+0B50h] ds:0023:f7737b50=00000000
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0073a esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up di pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046
nt!KiDispatchInterrupt+0x1a:
80b0073a 741e je nt!KiDispatchInterrupt+0x3a (80b0075a) [br=1]
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0075a esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up di pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046
nt!KiDispatchInterrupt+0x3a:
80b0075a fb sti
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0075b esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
nt!KiDispatchInterrupt+0x3b:
80b0075b 80bbe109000000 cmp byte ptr [ebx+9E1h],0 ds:0023:f77379e1=00
1: kd> bp 80b0075b
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00762 esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
nt!KiDispatchInterrupt+0x42:
80b00762 7577 jne nt!KiDispatchInterrupt+0xbb (80b007db) [br=0]
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b00764 esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
nt!KiDispatchInterrupt+0x44:
80b00764 83bb2801000000 cmp dword ptr [ebx+128h],0 ds:0023:f7737128=00000000
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b0076b esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
nt!KiDispatchInterrupt+0x4b:
80b0076b 746d je nt!KiDispatchInterrupt+0xba (80b007da) [br=1]
1: kd> p
eax=00000000 ebx=f7737000 ecx=8999d620 edx=80010031 esi=00000000 edi=804edc60
eip=80b007da esp=f78e6c9c ebp=f78e6ca0 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
nt!KiDispatchInterrupt+0xba:
80b007da c3 ret

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/30 1:49:54

15、字符串操作与动态HTML技术全解析

字符串操作与动态HTML技术全解析 1. 字符串操作基础回顾与拓展 在字符串操作领域,我们已经掌握了一些基础方法,如 charAt() 、 charCodeAt() 、 indexOf() 、 lastIndexOf() 、 substr() 、 substring() 、 toUpperCase() 、 toLowerCase() 以及 length …

作者头像 李华
网站建设 2026/3/27 23:16:54

Vue:如何实现日志导出下载功能?

提示&#xff1a;当前日志导出下载功能&#xff0c;是基于后端接口返回的日志数据url地址进行操作。 提示&#xff1a;当前日志导出下载功能&#xff0c;是基于后端接口返回的日志数据url地址进行操作。 提示&#xff1a;当前日志导出下载功能&#xff0c;是基于后端接口返回…

作者头像 李华
网站建设 2026/3/31 15:51:34

Vue:如何实现一个具有复制功能的文字按钮?

实现一个具有复制功能的文字按钮 通过点击按钮实现指定文字的复制功能。 文章目录1.效果图2.关键代码总结1.效果图 2.关键代码 #template <span id"copycontent">{{web_url}}</span><button style"position: relative; top: -2px;left: 5px;&qu…

作者头像 李华
网站建设 2026/3/26 10:46:24

奇怪的PCB设计知识又增加了:听都没听过的电容,滤波性能竟然这么好?

高速先生成员-- 黄刚 在电源网络中&#xff0c;电容主要是起到去耦滤波的作用&#xff0c;在高速先生的很多文章中都分享过这个基础的概念了&#xff0c;就好像下面的示意图一样。不同封装和容值的电容放到电源链路中的不同位置&#xff0c;能够对不同的频率进行滤波。例如放在…

作者头像 李华
网站建设 2026/3/30 17:45:51

内网常见攻击手段与防御措施对照表

攻击阶段攻击手段核心原理典型工具防御措施一、信息收集1. 内网存活主机探测&#xff08;ARP/ICMP 扫描&#xff09;利用 ARP 广播或 ICMP 请求识别活跃主机&#xff0c;无扫描特征或特征弱arp-scan、fping、nmap -sn1. 部署内网防火墙&#xff0c;限制非授权主机的 ARP 扫描请…

作者头像 李华
网站建设 2026/3/26 21:41:11

验证码识别

验证码识别 验证码的用途和分类 验证码的作用 验证身份&#xff1a;代表是你在做的 使用手机号/邮箱登录 敏感操作二次验证&#xff1a;异地登录&#xff0c;修改密码&#xff0c;注销等 验证行为&#xff1a; 机器批量操作&#xff1a;投票&#xff0c;抢购&#xff0c…

作者头像 李华