用户层APC队列使用

Posted talenth

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用户层APC队列使用相关的知识,希望对你有一定的参考价值。

一 参考

https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-queueuserapc

<<windows核心编程>> 第5版

 

二 每个线程都有一个APC队列, 在线程处于可警醒状态时, 线程会执行APC队列中apc函数

  经过以上参考文章加上测试发现, APC队列中的函数会在以下3个时机调用

  1 线程已经创建, 系统在调用线程函数时会检查APC队列, 如果不为空, 则调用APC队列中的apc函数, 直到队列为空后, 才开始调用线程函数

  2 线程通过WaitForSingleObjectEx等函数进入可警醒状态时, 会先检查APC队列, 如果不为空, 则调用APC队列中的apc函数, 直到队列为空后, 才开始等待要等待的对象, 此时如果要等待的对象没有进入激发态且没有超时WaitForSingleObjectEx不会返回

  3 线程通过WaitForSingleObjectEx等函数进入可警醒状态时, APC队列为空, 且要等待的对象没有进入激发态, 也没有超时, 则线程进入睡眠等待状态, 此时往该APC队列添加APC函数后, 该线程会被唤醒执行完所有APC队列中的函数, 然后不去看要等待的对象是否进入激发态, 立即从WaitForSingleObjectEx中返回, 返回值是WAIT_IO_COMPLETION 

测试代码如下

 1 #include <windows.h>
 2 #include <iostream>
 3 #include <process.h>
 4 
 5 HANDLE hEvent = NULL;
 6 HANDLE HMainEvent = NULL;
 7 DWORD WINAPI TestProc(LPVOID lpThreadParameter)
 8 {
 9     printf("thread start
");
10     SetEvent(HMainEvent);
11     if (hEvent && hEvent != INVALID_HANDLE_VALUE)
12     {
13         printf("waitfor start
");
14         DWORD ret = WaitForSingleObjectEx(hEvent, INFINITE, TRUE);
15         //WAIT_OBJECT_0
16         printf("waitfor ret= 0x%08x
", ret);
17     }
18     printf("thread end
");
19     return 0;
20 }
21 VOID NTAPI TestAPC(ULONG_PTR Parameter)
22 {
23     printf("apc func start index=%u
",Parameter);
24 }
25 int main(int argc, char **argv, char **env)
26 {
27     HANDLE hT = NULL;
28     hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
29     HMainEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
30 
31     if (hEvent)
32     {
33         hT = (HANDLE)_beginthreadex(NULL, 0, (_beginthreadex_proc_type)TestProc, NULL, 0, NULL);
34         if (hT && hT != INVALID_HANDLE_VALUE)
35         {
36             WaitForSingleObject(HMainEvent, INFINITE);
37             //Sleep(2000);
38             ULONG_PTR index = 1;
39             for(;index <100;++index)
40             {
41                 QueueUserAPC(TestAPC, hT, index);
42             }
43             Sleep(2000);
44             SetEvent(hEvent);
45             WaitForSingleObject(hT, INFINITE);
46         }
47     }
48     CloseHandle(hEvent);
49     CloseHandle(HMainEvent);
50     CloseHandle(hT);
51     system("pause");
52     return 0;
53 }

 

以上是关于用户层APC队列使用的主要内容,如果未能解决你的问题,请参考以下文章

备用APC队列

Ring3 APC注入

基于Wrk和ReactOS源码分析APC机制的记录

APC注入(Ring3层)

Windows x86/ x64 Ring3层注入Dll总结

php可选缓存APC