4.内核APC执行过程
APC函数的执行与插入并不是同一个线程:
在A线程中向B线程插入一个APC,插入的动作是在A线程中完成的,但什么时候执行则由B线程决定!,所以叫“异步过程调用"
内核APC函数与用户APC函数的执行时间和执行方式也有区别,我们本节课主要学习内核APC的执行过程。
执行点1:线程切换
SwapContext //判断是否有内核APC
KiSwapThread
KiDelicerApc //执行内核APC函数
在SwapContext快结束的时候做了一个判断,判断的结果存到EAX中,然后返回。
一直到这里才开始处理
执行点2:系统调用、中断或者异常(_KiServiceExit)
当要执行用户APC之前,先要执行内核APC。
KiDeliverApc函数执行流程
- 判断第一个链表是否为空
- 判断KTHREAD.ApcState.KernelApclnProgress是否为1
- 判断是否禁用内核APC(KTHREAD.KernelApcDisable是否为1).
- 将当前KAPC结构体从链表中摘除
- 执行KAPC.KernelRoutine指定的函数释放KAPC结构体占用的空间
- 将KTHREAD.ApcState.KernelApclnProgress设置为1标识正在执行内核APC
- 执行真正的内核APC函数(KAPC.NormalRoutine)
- 执行完毕将KernelApcInProgress改为0
如果链表不为空,把4个要用的放到局部变量里
如果NormalRoutine不为空就跳到这(不知道NormalRoutine是什么的去看《3.APC的挂入过程》)
9.下一个循环又跳回来
总结:
- 内核APC在线程切换的时候就会执行,这也就意味着,只要插入内核APC·很快就会执行。
- 在执行用户APC之前会先执行内核APC
- 内核APC在内核空间执行,不需要换栈,一个循环全部执行完毕。