一、KeInsertQueueApc(调用 KiInsertQueueApc)

BOOLEAN
KeInsertQueueApc (IN PRKAPC Apc,IN PVOID SystemArgument1,IN PVOID SystemArgument2,IN KPRIORITY Increment)/*++Routine Description:This function inserts an APC object into the APC queue specifed by thethread and processor mode fields of the APC object. If the APC objectis already in an APC queue or APC queuing is disabled, then no operationis performed. Otherwise the APC object is inserted in the specified queueand appropriate scheduling decisions are made.插入 APC 到指定线程的APC队列,用户态和内核态分别插入对应的 APC 队列。如果 APC 对象已经在 APC 队列或者 APC 队列被禁用(例如线程正在退出),则不执行操作。否则插入 APC 对象并调用相应的函数。Arguments:Apc - Supplies a pointer to a control object of type APC.APC 结构SystemArgument1, SystemArgument2 - Supply a set of two arguments thatcontain untyped data provided by the executive.传给 APC 函数的参数。Increment - Supplies the priority increment that is to be applied ifqueuing the APC causes a thread wait to be satisfied.线程优先级增量Return Value:If the APC object is already in an APC queue or APC queuing is disabled,then a value of FALSE is returned. Otherwise a value of TRUE is returned.--*/{BOOLEAN Inserted;KLOCK_QUEUE_HANDLE LockHandle;KIRQL OldIrql;PRKTHREAD Thread;ASSERT_APC(Apc);ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);//// Raise IRQL to SYNCH_LEVEL, acquire the thread APC queue lock, and lock// the dispatcher database.// 提升 IRQL 等级,申请 APC 锁,锁 dispatcher databaseThread = Apc->Thread;KeAcquireInStackQueuedSpinLockRaiseToSynch(&Thread->ApcQueueLock, &LockHandle);KiLockDispatcherDatabaseAtSynchLevel();//// If APC queuing is disabled, then set inserted to FALSE. Else save// system parameter values in APC object, and attempt to queue APC.// 调用 KiInsertQueueApcif (Thread->ApcQueueable == FALSE) {Inserted = FALSE;} else {Apc->SystemArgument1 = SystemArgument1;Apc->SystemArgument2 = SystemArgument2;Inserted = KiInsertQueueApc(Apc, Increment);}//// Unlock the dispatcher database from SYNCH_LEVEL, unlock the thread APC// queue lock and lower IRQL to its previous value, and return whether the// APC was inserted.//KiUnlockDispatcherDatabaseFromSynchLevel();KeReleaseInStackQueuedSpinLock(&LockHandle);return Inserted;
}

二、KiInsertQueueApc

BOOLEAN
FASTCALL
KiInsertQueueApc (IN PKAPC Apc,IN KPRIORITY Increment)/*++Routine Description:This function inserts an APC object into a thread's APC queue. The addressof the thread object, the APC queue, and the type of APC are all derivedfrom the APC object. If the APC object is already in an APC queue, thenno opertion is performed and a function value of FALSE is returned. Elsethe APC is inserted in the specified APC queue, its inserted state is setto TRUE, and a function value of TRUE is returned. The APC will actuallybe delivered when proper enabling conditions exist.N.B. The thread APC queue lock and the dispatcher database lock must bothbe held when this routine is called.Arguments:Apc - Supplies a pointer to a control object of type APC.Increment - Supplies the priority increment that is to be applied ifqueuing the APC causes a thread wait to be satisfied.Return Value:If the APC object is already in an APC queue, then a value of FALSE isreturned. Else a value of TRUE is returned.--*/{KPROCESSOR_MODE ApcMode;PKAPC ApcEntry;PKAPC_STATE ApcState;BOOLEAN Inserted;PLIST_ENTRY ListEntry;PKTHREAD Thread;//// If the APC object is already in an APC queue, then set inserted to// FALSE. Else insert the APC object in the proper queue, set the APC// inserted state to TRUE, check to determine if the APC should be delivered// immediately, and set inserted to TRUE.//// For multiprocessor performance, the following code utilizes the fact// that kernel APC disable count is incremented before checking whether// the kernel APC queue is nonempty.//// See KeLeaveCriticalRegion().//Thread = Apc->Thread;if (Apc->Inserted) {Inserted = FALSE;} else {//typedef enum _KAPC_ENVIRONMENT {// OriginalApcEnvironment, // 所属进程(创建线程的进程,父进程)// AttachedApcEnvironment, // 挂靠进程//   CurrentApcEnvironment,  // 当前环境,提供CR3的进程(正常状态是所属进程,挂靠状态是挂靠进程)//    InsertApcEnvironment    // 插入APC时的环境//} KAPC_ENVIRONMENT;// Apc->ApcStateIndex 是在 KeInitializeApc 函数内初始化的,它的值决定了插入到哪个进程的APC队列(所属进程 还是 挂靠进程)// // 终止线程的 PspTerminateThreadByPointer 和3环 QueueUserApc , Apc->ApcStateIndex 都是 0// 0意味着选择所属进程,因为不挂靠时 ApcStatePointer[0] 是所属线程;挂靠时 ApcStatePointer[0] 还是所属线程的备份if (Apc->ApcStateIndex == InsertApcEnvironment) {// 插入前实时地从 Thread 里取//设计 InsertApcEnvironment 也许是考虑到初始化时和插入前线程的状态可以发生改变Apc->ApcStateIndex = Thread->ApcStateIndex;}ApcState = Thread->ApcStatePointer[Apc->ApcStateIndex];//// Insert the APC after all other special APC entries selected by// the processor mode if the normal routine value is NULL. Else// insert the APC object at the tail of the APC queue selected by// the processor mode unless the APC mode is user and the address// of the special APC routine is exit thread, in which case insert// the APC at the front of the list and set user APC pending.//ApcMode = Apc->ApcMode; // 内核APC or 用户APCif (Apc->NormalRoutine != NULL) {// NormalRoutine 非空,就在这里插入// NormalRoutine 是 所有用户APC函数的入口 或者 内核APC函数,取决于APC是用户模式还是内核模式if ((ApcMode != KernelMode) && (Apc->KernelRoutine == PsExitSpecialApc)) {// 是用户APC,并且 KernelRoutine == PsExitSpecialApc ,3环调用 QueueUserApc 就是这种情况// 标记已插入Thread->ApcState.UserApcPending = TRUE;// 插入到队列头部InsertHeadList(&ApcState->ApcListHead[ApcMode],&Apc->ApcListEntry);} else {// 内核APC,比较简单,直接插入队列尾部InsertTailList(&ApcState->ApcListHead[ApcMode],&Apc->ApcListEntry);}} else {// NormalRoutine 是 NULL ,走这里// 从队尾开始遍历 APC 队列// 直到找到下一个 NormalRoutine 为空的APCListEntry = ApcState->ApcListHead[ApcMode].Blink;while (ListEntry != &ApcState->ApcListHead[ApcMode]) {ApcEntry = CONTAINING_RECORD(ListEntry, KAPC, ApcListEntry);if (ApcEntry->NormalRoutine == NULL) {break;}ListEntry = ListEntry->Blink;}// 插入到队列头部InsertHeadList(ListEntry, &Apc->ApcListEntry);}// 插入成功Apc->Inserted = TRUE;//// If the APC index from the APC object matches the APC Index of// the thread, then check to determine if the APC should interrupt// thread execution or sequence the thread out of a wait state.//// 条件成立,APC 和当前线程使用同一个进程// 要么没有attach,APC插入了所属进程// 要么attach了,APC插入的也是挂靠的进程if (Apc->ApcStateIndex == Thread->ApcStateIndex) {//// If the processor mode of the APC is kernel, then check if// the APC should either interrupt the thread or sequence the// thread out of a Waiting state. Else check if the APC should// sequence the thread out of an alertable Waiting state.//if (ApcMode == KernelMode) {// 标记已插入内核APCThread->ApcState.KernelApcPending = TRUE;if (Thread->State == Running) {// 如果线程正在运行,则 APC 中断KiRequestApcInterrupt(Thread->NextProcessor);} else if ((Thread->State == Waiting) &&       // 线程阻塞(等待)(Thread->WaitIrql == 0) &&((Apc->NormalRoutine == NULL) ||((Thread->KernelApcDisable == 0) &&(Thread->ApcState.KernelApcInProgress == FALSE)))) // 没有正在执行的 APC{// 修改线程状态为就绪,提升优先级KiUnwaitThread(Thread, STATUS_KERNEL_APC, Increment, NULL);}} else if ((Thread->State == Waiting) &&                          // 线程处于阻塞状态(Thread->WaitMode == UserMode) &&                           // 用户导致的阻塞(Thread->Alertable || Thread->ApcState.UserApcPending)) // 是否可以被APC唤醒或者已经插入,SleepEx 可以设置 Alertable{Thread->ApcState.UserApcPending = TRUE;// 修改线程状态为就绪,提升优先级KiUnwaitThread(Thread, STATUS_USER_APC, Increment, NULL);}}Inserted = TRUE;}//// Return whether the APC object was inserted in an APC queue.//return Inserted;
}

(74)分析 APC 插入过程 —— KeInsertQueueApc , KiInsertQueueApc相关推荐

  1. (75)内核APC执行过程,分析 KiDeliverApc 函数

    一.内核APC执行过程 通过分析 SwapContext ,KiSwapContexgt , KiSwapThread ,我们得出一个结论:切换线程后会执行内核APC,调用的函数是 KiDeliver ...

  2. [6]Windows内核情景分析 --APC

    APC:异步过程调用.这是一种常见的技术.前面进程启动的初始过程就是:主线程在内核构造好运行环境后,从KiThreadStartup开始运行,然后调用PspUserThreadStartup,在该线程 ...

  3. 4.内核APC执行过程

    APC函数的执行与插入并不是同一个线程: 在A线程中向B线程插入一个APC,插入的动作是在A线程中完成的,但什么时候执行则由B线程决定!,所以叫"异步过程调用" 内核APC函数与用 ...

  4. 【转】 浏览器分析模拟登陆过程

    原文地址:http://www.crifan.com/use_ie9_f12_to_analysis_the_internal_logical_process_of_login_baidu_main_ ...

  5. mysql 导入主键冲突_MySQL 处理插入过程中的主键唯一键重复值的解决方法

    本篇文章主要介绍在插入数据到表中遇到键重复避免插入重复值的处理方法,主要涉及到IGNORE,ON DUPLICATE KEY UPDATE,REPLACE:接下来就分别看看这三种方式的处理办法. IG ...

  6. DispatcherServlet代码分析及运行过程

    DispatcherServlet代码分析及运行过程 1    首先该类有一静态语块,用以加载缺省策略. static { ClassPathResource resource =new ClassP ...

  7. 三十、电子商务分析与服务推荐的分析方法与过程

    1. 分析方法与过程 1.1 目标 本案例的目标是对用户进行推荐,即以一定的方式将用户与物品之间建立联系.为了更好地帮助用户从海量的数据中快速发现感兴趣的网页,在目前相对单一的推荐系统上进行补充.电子 ...

  8. POE供电交换机技术分析及工作过程详解

    PoE供电是指在以太网中透过双绞线来将电力传输到设备的技术,它无需改动现有的以太网布线基础架构,在为一些基于IP的终端传输数据信号的同时,还能为此类设备提供直流供电.透过这项技术,可以供电给网路电话. ...

  9. 《大话软件工程—需求分析与软件设计》,给出了分析与设计过程中需要的理论、方法、工具和标准

    □ 做好一款软件从哪里开始呢?→ 客户需求的调研: □ 一款软件的价值高低由哪个环节决定呢?→ 软件的分析与设计: □ 软件顺利完成开发靠什么?→ 高效的项目管理: □ 软件开发的主要角色?→ 客户. ...

最新文章

  1. 「苹果牌」电动车要来了:最早明年见,还带着突破性电池技术
  2. 华为M2 e服务器信息解析失败,关于华为:华为审核被拒检查HMS-Core更新失败
  3. 解决报错:错误1130- Host xxx is not allowed to connect to this MariaDb server
  4. Penang Industrial Zone
  5. 使用ThreadPoolExecutor并行化独立的单线程任务
  6. idea 新增html页面或者是修改html文件后,target不会同步更新
  7. 2012二级java真题_2012年计算机二级JAVA模拟试题及答案详解汇总
  8. indy idhttpserver有关下载的两个问题
  9. scala 基础类库 —— 文件操作
  10. 20190608每日一句
  11. DocsBuilderGUI 工具使用介绍
  12. Java程序员职业规划
  13. 简单的js在html页面打印机,在javaScript中如何连接打印机
  14. API是什么意思,具体是什么?
  15. 记忆测试系统java代码_JAVA课程设计——记忆测试系统(附源程序).doc
  16. 派森编程软件python有什么用_派森Python下载
  17. 不只是CAD电子签名,设计院电子签章还要有这些!
  18. windows开机启动自定义程序和任务
  19. 乐普生物上市一度破发:收盘市值118亿 年亏损超10亿
  20. 《秒懂EXCEL》重点复习笔记01

热门文章

  1. 什么是机房三维(3D)监控系统,什么是机房可视化动力环境监控系统?
  2. 数据中心UPS电池故障引起火灾导致澳大利亚医院系统业务中断
  3. 两个service事务统一_RocketMQ进阶 - 事务消息
  4. java des加密解密_JAVA和c# 之间数据通讯时通过DES进行加密解密
  5. Docker:Docker的简介、安装、使用方法之详细攻略
  6. NLP之词向量:利用word2vec对20类新闻文本数据集进行词向量训练、测试(某个单词的相关词汇)
  7. TF之p2p:基于TF利用p2p模型部分代码实现提高图像的分辨率
  8. C#事件与委托的区别
  9. Native C++ _isnan()函数的应用
  10. 【数据库】分库分表策略