一、回顾

第71篇博客我们分析了 PspTerminateThreadByPointer 函数,其中调用了 KeInitializeApc 函数初始化 KAPC 结果。这次课我们来分析 KeInitializeApc 函数,了解 APC 如何初始化。

PspTerminateThreadByPointer(psdelete.c) 调用 KeInitializeApc

KeInitializeApc (ExitApc,PsGetKernelThread (Thread),OriginalApcEnvironment,      // 父进程PsExitSpecialApc,             // 释放APC内存,退出当前线程PspExitApcRundown,              // 释放APC内存PspExitNormalApc,             KernelMode,                 // 内核模式ULongToPtr (ExitStatus));        // 线程退出码

NtQueueApcThread(psctx.c) 调用 KeInitializeApc

KeInitializeApc (Apc,&Thread->Tcb,OriginalApcEnvironment,         // 插入到所属进程(创建线程的那个进程)PspQueueApcSpecialApc,           // KernelRoutine , 作用是释放 APC 内存(ExFreePool)NULL,                           // RundownRoutine 未指定(PKNORMAL_ROUTINE)ApcRoutine,  // 用户APC总入口 BaseDispatchAPC(3环函数)UserMode,                        // 用户模式APCApcArgument1);                    // 3环APC函数

二、KeInitializeApc (apcobj.c)

这个函数比较简单,就是初始化,最难理解的是 ApcStateIndex ,我已经在注释里写清楚了,还是不懂的话,可以结合 KiInsertQueueApc 函数来分析 ApcStateIndex 的用途。

VOID
KeInitializeApc (IN PRKAPC Apc,                                 // APC结构体指针IN PRKTHREAD Thread,                         // 要插入APC的目标线程IN KAPC_ENVIRONMENT Environment,              // 四种环境状态,包括父进程,挂靠进程,当前进程(提供CR3的进程),插入时的当前进程IN PKKERNEL_ROUTINE KernelRoutine,                // 不管是用户APC还是内核APC,这个函数的共同作用是释放APC;内核APC可能会有额外的功能,如退出、挂起、恢复线程IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL, // 如果是用户APC,这里是NULL;如果是要求退出线程的内核APC,这里是 PspExitApcRundownIN PKNORMAL_ROUTINE NormalRoutine OPTIONAL,       // 如果是用户APC,这里是 BaseDispatchAPC(3环函数);// 如果是内核APC,这里就是内核APC函数IN KPROCESSOR_MODE ApcMode OPTIONAL,            // 用户模式 / 内核模式IN PVOID NormalContext OPTIONAL                   // 如果是用户APC,这里就是3环提供的APC函数的参数)/*++Routine Description:This function initializes a kernel APC object. The thread, kernelroutine, and optionally a normal routine, processor mode, and normalcontext parameter are stored in the APC object.分配空间,初始化KAPC结构体Arguments:Apc - Supplies a pointer to a control object of type APC.Thread - Supplies a pointer to a dispatcher object of type thread.Environment - Supplies the environment in which the APC will execute.Valid values for this parameter are: OriginalApcEnvironment,AttachedApcEnvironment, CurrentApcEnvironment, or InsertApcEnvironmentKernelRoutine - Supplies a pointer to a function that is to beexecuted at IRQL APC_LEVEL in kernel mode.RundownRoutine - Supplies an optional pointer to a function that is to becalled if the APC is in a thread's APC queue when the thread terminates.NormalRoutine - Supplies an optional pointer to a function that isto be executed at IRQL 0 in the specified processor mode. If thisparameter is not specified, then the ProcessorMode and NormalContextparameters are ignored.ApcMode - Supplies the processor mode in which the function specifiedby the NormalRoutine parameter is to be executed.NormalContext - Supplies a pointer to an arbitrary data structure which isto be passed to the function specified by the NormalRoutine parameter. Return Value:None.--*/{ASSERT(Environment <= InsertApcEnvironment);//// Initialize standard control object header.//Apc->Type = ApcObject; // 0x12 内核对象类型Apc->Size = sizeof(KAPC);//// Initialize the APC environment, thread address, kernel routine address,// rundown routine address, normal routine address, processor mode, and// normal context parameter. If the normal routine address is null, then// the processor mode is defaulted to KernelMode and the APC is a special// APC. Otherwise, the processor mode is taken from the argument list.////typedef enum _KAPC_ENVIRONMENT {//  OriginalApcEnvironment, // 所属进程(创建线程的进程)//    AttachedApcEnvironment, // 挂靠进程//   CurrentApcEnvironment,  // 当前环境,提供CR3的进程(正常状态是所属进程,挂靠状态是挂靠进程)//    InsertApcEnvironment    // 插入APC时的环境//} KAPC_ENVIRONMENT;// ApcStateIndex 决定了挂到哪个进程的APC队列if (Environment == CurrentApcEnvironment) {// 如果要求的是当前状态,那么就从 Thread->ApcStateIndex 里取值,如果当前没有挂靠,则是0,;如果挂靠了,就是1.Apc->ApcStateIndex = Thread->ApcStateIndex;} else {ASSERT((Environment <= Thread->ApcStateIndex) || (Environment == InsertApcEnvironment));// 否则就默认插入到所属进程(创建线程的进程)的APC队列里Apc->ApcStateIndex = (CCHAR)Environment;}Apc->Thread = Thread;                 // 目标线程Apc->KernelRoutine = KernelRoutine;      // 主要功能是释放APCApc->RundownRoutine = RundownRoutine;  // 可选,退出线程时会用到Apc->NormalRoutine = NormalRoutine;        // 如果是用户APC,这里是 BaseDispatchAPC(3环函数);// 如果是内核APC,这里就是内核APC函数if (ARGUMENT_PRESENT(NormalRoutine)) {Apc->ApcMode = ApcMode; // 0内核,1用户Apc->NormalContext = NormalContext; // 内核APC:NULL;用户APC:真正的APC函数} else {Apc->ApcMode = KernelMode;Apc->NormalContext = NIL; // NULL}Apc->Inserted = FALSE;return;
}

(73)分析 KeInitializeApc ,了解 KAPC 的初始化相关推荐

  1. Bochs源码分析 - 6: bochs的物理内存初始化

    前言 上一篇文章,我们走马观花地介绍了bochs从启动到CPU执行流程的大体流程,里面相关数据结构没详细分析.这篇文章我们尝试来详细分析一下bochs的物理内存初始化,首先有个概念需要理清(相信来看b ...

  2. Python3.5源码分析-内建模块builtins初始化

    Python3源码分析 本文环境python3.5.2. 参考书籍<<Python源码剖析>> python官网 Python3模块初始化与加载 Python的模块分为内建的模 ...

  3. HDFS源码分析心跳汇报之数据结构初始化

    在<HDFS源码分析心跳汇报之整体结构>一文中,我们详细了解了HDFS中关于心跳的整体结构,知道了BlockPoolManager.BPOfferService和BPServiceActo ...

  4. u-boot分析(八)----串口初始化

    u-boot分析(八) 上篇博文我们按照210的启动流程,分析到了内存初始化,今天我们继续按照u-boot的启动流程对串口的初始化进行分析. 今天我们会用到的文档: 1.        2440芯片手 ...

  5. 【中级】【后台】 微信小程序 - 腾讯云 - wafer2 - PHP - DEMO - 003 - 源码分析 - 03 - 腾讯后台初始化 和 CodeIgniter

    本文原创,欢迎转载,但是,务必保持原文并且给出原文链接. 前言: 本节对Wafer 服务端 SDK 是腾讯云为微信小程序开发者提供的快速开发库,SDK 封装了以下功能供小程序开发者快速调用的源码的初始 ...

  6. Redis 的 Sentinel哨兵介绍与源码分析(1):初始化部分

    http://www.redis.cn/topics/sentinel.html redis-6.0.8 本文是在官方中文文档的基础上进行的源码分析,其中包含完整的原文,并在此基础上,添加源码介绍. ...

  7. DRM框架(vkms)分析(4)----encoder初始化

    本文 主要分析encoder的初始化和配置,drm_encoder结构体如下: /*** struct drm_encoder - central DRM encoder structure* @de ...

  8. 基于armv8的kvm实现分析(三)kvm初始化流程

    本文基于以下软硬件假定: 架构:AARCH64 内核版本:5.14.0-rc5 1 kvm概述 kvm是基于linux内核实现的一种type 2虚拟化方案,它作为内核的一个模块负责虚拟化环境初始化,虚 ...

  9. Generic Netlink内核实现分析(一):初始化

    Generic Netlink 是内核专门为了扩展netlink协议簇而设计的"通用netlink协议簇".由于netlink协议最多支持32个协议簇,目前Linux4.1的内核中 ...

最新文章

  1. 解决虚拟机linux端mysql数据库无法远程访问
  2. 函数、装饰器、迭代器、内置方法总练习题
  3. mysql 403_mysql数据库管理phpmyadmin 403错误的解决方法
  4. 01 按指定格式读写文件出现乱码
  5. C++自增自减运算符简单记录
  6. 【Android】安卓闪电复习
  7. phpstudy php56 zend,phpstudy集成环境
  8. 2019 年各地移动 APT事件总结
  9. 回答老板“明白了”,可真的明白了吗?
  10. Linux查询系统上次启动时间last reboot、上线时间uptime
  11. win7系统传奇如何架服务器,win7系统如何架设传奇服务端玩游戏更流畅
  12. 为什么很多人上了研究生变得不快乐了?
  13. win10锁屏幻灯片放映不能播放幻灯片问题的一种解决办法
  14. Ribbon负载均衡原理,源码解读
  15. linux学习教程-硬盘介绍和磁盘管理v11
  16. Microsoft.Office.Interop.Word通过模板生成文档出现的问题经验总结
  17. 用python定义两个元组_python初学-元组、集合
  18. ipad iphone开发_如何在iPhone或iPad上取消应用订阅
  19. 陆奇举刀,百度第三次重组内阁
  20. html音乐播放器标签,打造属于自己的音乐播放器 HTML5之audio标签

热门文章

  1. php mysql 表字段_php mysql获取表字段名称和字段信息的三种方法
  2. mysql mysqlhotcopy_MySQL备份工具之mysqlhotcopy
  3. DL之DNN优化技术:利用Batch Normalization(简介、入门、使用)优化方法提高DNN模型的性能
  4. 成功解决File amp;quot;f:\program files\python\python36\lib\re.pyamp;quot;, line 142, in amp;lt;modul
  5. Python 中的 lstrip、rstrip、strip
  6. 配置Docker代理已实现外网访问
  7. Oracle Proc开发之Makefile的编写模板
  8. 配置ip地址四种方法,方便学习linux的朋友
  9. Objective-C 文件夹操作
  10. [转载]细说ASP.NET Windows身份认证