先说两个典型的应用
1. IoCompleteRequest内部实现,实现在任意上下文的时候,插入kernel APC,把IO操作结果返给相应的线程。
2. Set/Get 上下文的内部实现。
User mode APC:在系统进入Alert状态才会Deliver ,可以参考KeWaitXXXX系列函数,KeTestAlertThread可以返回是否Altert状态。
Kernel mode APC:分为Regular和Speical ,其中Speical kernel mode APC会每次插入到队列的前面,会优先达到指定线程。
Windows有个功能就是当前Process可以临时Attach到别的Process中去,为了在别的Process中的时候依然可以处理APC,KTHREAD结构中存储两个APC Envirnment。
主的是ApcState,辅的是SavedApcState。ApcState总是记录当时线程收到的APC。
1.普通情况下使用ApcState,此时ApcStateIndex 为OriginalApcEnvironment。ApcStatePointer[OriginalApcEnvironment]指向ApcState。
2.当Attach到别的Process时,此时ApcStateIndex 为AttachedApcEnvironment,备份ApcState到SavedApcState,当插入的APC被放入ApcState。ApcStatePointer[OriginalApcEnvironment]指向SavedApcState,ApcStatePointer[AttachedApcEnvironment]指向SavedApcState。
使用APC
1. KeInitializeApc。注意区分KernelRoutine,RundownRoutine,NormalRoutine。
对于Special kernel mode APC: NormalRoutine为NULL。
对于Regular kernel mode APC:NormalRoutine非NULL,同时指定mode为kernel mode。
对于User mode APC:NormalRoutine非NULL,同时指定mode为user mode。
2. KeInsertQueueApc。
另外,NtQueueApcThread可以插入user mode APC,它内部其实调用了KeInitializeApc和KeInsertQueueApc。
QueueUserAPC内部就是调用NtQueueApcThread。