这与我以前的问题有关SleepEx
的实际工作方式有些相关。文档说,每当apc排队时,执行SleepEx
的线程被恢复,并且在线程已经执行APC时,APC可能会继续排队。
那么线程多长时间继续执行APC?是否在检查时队列为空之前,并且在那一刻,SleepEx
将控制权返回到呼叫者?或者只是该线程执行的一个APC,然后SleepEx
返回,另一个APC的执行将需要SleepEx
再一次称为一次?
我感觉到APC被执行,直到排队第一次为空为止。谢谢!
apcs被执行,直到队列为空为止。当您从APC返回的代码是插入的另一个APC时 - 如果是 - Next apc 被执行,直到线程中不再插入APC为止。此后SleepEx
(或任何其他可警报的等待API)将控件返回到您
以下方式执行的APC - 当您调用某些API时(SleepEx
,MsgWaitForMultipleObjectsEx
,WaitForSingleObjectEx
,WaitForMultipleObjectsEx
..将函数的balertable参数设置为true)插入apc在线程对象中。如果是 - 内核将用户模式线程上下文复制到堆栈,而不是更改线程上下文(用户模式返回地址设置为ntdll.KiUserApcDispatcher
)并返回。作为结果代码,不是从他输入到内核的位置返回(如果SleepEx
这是ZwDelayExecution
,它在内部调用),而是KiUserApcDispatcher
。此API执行 apc ,然后致电ZwContinue
。此API宣布为:
NTSYSAPI NTSTATUS NTAPI ZwContinue(PCONTEXT Context, BOOLEAN TestAlert);
在堆栈线程上下文中保存的上下文中,以返回到该点,从中调用了可警报的API,TestAlert
指定是否应检查插入其他APC。如果使用TestAlert == FALSE
系统调用ZwContinue
,则直到您自己不致电SleepEx
或其他某些API之前,将不会更多地检查APC。但是在KiUserApcDispatcher
TestAlert
中,硬编码为TRUE
-如果理解的汇编代码(KiUserApcDispatcher
很小),您可以轻松地自己看一下。