SleepEx期间处理了多少个APC?

时间:2017-09-14 14:23:23

标签: windows multithreading sleep

这与former question我的SleepEx实际如何运作有些关联。 The docs表示只要APC排队,执行SleepEx的线程就会恢复,并且当线程已经执行APC时,APC可能会继续排队。

那么线程持续执行APC需要多长时间?是否每当检查时队列为空,并且在那一刻SleepEx将控制返回给调用者?或者只是该线程执行的一个APC,然后SleepEx返回,另一次执行APC需要再次调用SleepEx

我感觉APC一直被执行,直到队列第一次为空。谢谢!

1 个答案:

答案 0 :(得分:2)

执行APC直到队列为空。当您的代码从APC返回时 - 系统检查是另一个插入的APC - 如果是 - 下一个 APC 执行,直到线程中不再插入APC。在此SleepEx之后(或任何其他可警告的等待API)将控制权交还给您

以下一种方式执行的APC - 当您调用某个api(SleepExMsgWaitForMultipleObjectsExWaitForSingleObjectExWaitForMultipleObjectsEx ..并将函数的bAlertable参数设置为TRUE时内核检查是在线程对象中插入的APC。如果是 - 内核将用户模式线程上下文复制到它的堆栈,而不是将线程上下文(用户模式返回地址设置为ntdll.KiUserApcDispatcher)并返回。结果代码不是从他进入内核的地方返回的(如果SleepEx这是ZwDelayExecution,它是内部调用的),而是返回KiUserApcDispatcher。此api执行 APC ,然后调用ZwContinue。这个api声明为:

NTSYSAPI NTSTATUS NTAPI ZwContinue(PCONTEXT Context, BOOLEAN TestAlert);

就位使用上下文保存在堆栈线程上下文中,返回到调用可警告api的点,TestAlert指定是否应该检查是否插入了额外的apc。如果用ZwContinue系统调用TestAlert == FALSE将不再检查线程队列中的APC,直到你自己没有调用SleepEx或其他特定的api - 那么将完全执行1个APC。但是在KiUserApcDispatcher TestAlert硬编码到TRUE - 如果您了解汇编代码(KiUserApcDispatcher很小),您可以自己查看这些内容

相关问题