Asynchronous Procedure Calls (APCs) are a fundamental building block in NT's asynchronous processing architecture. An understanding of this mechanism is essential to better understand how NT works and performs several core system operations.
Basically, APCs allow user programs and system components to execute code in the context of a particular thread and, therefore, within the address space of a particular process. The I/O Manager executive subsystem, for example, uses APCs to complete I/O operations initiated asynchronously. When a device driver calls IoCompleteRequest to notify the I/O Manager that it is through processing an asynchronous I/O request, the I/O subsystem queues an APC to the thread that initiated the I/O request. The next time the thread runs at low IRQL, the pending APC is delivered. This APC's role is copying the results of the I/O operation and status information from system memory into a buffer in the thread's virtual address space. Other interesting ways that APCs are used in NT are to get or set a thread's context and to suspend a thread's execution. The POSIX environment subsystem also uses APCs to simulate the delivery of POSIX signals to POSIX processes.
Although APCs are extensively used throughout NT, documentation on how to use them is completely lacking. In this article, I'll detail how NT processes APCs and document the exported NT functions available to device-driver writers to use APCs in their programs. I'll also show a most-likely implementation of the NT's APC dispatcher subroutine KiDeliverApc to allow you to better grasp the inners of APC delivery.
APC Objects
In NT there are two possible kinds of APCs: user mode and kernel mode. User APCs execute in user mode in the target thread's current process context and require "permission" from that thread to run. Specifically, user-mode APCs require the target thread to be in an alertable wait state for being successfully delivered. A thread enters such a state by calling one of the system functions KeWaitForSingleObject, KeWaitForMultipleObjects, KeWaitForMutexObject, or KeDelayExecutionThread and specifying the wait as "alertable." Alternatively, a user thread can cause user-mode APCs to be delivered to it by calling the undocumented alert-test service KeTestAlertThread.
When a user-mode APC is delivered to a thread waiting alertably, the wait state is satisfied with the completion status STATUS_USER_APC. On return to user mode, the kernel transfers control to the APC routine and resumes the thread's execution when the APC routine completes.
In contrast to user APCs, kernel APCs execute in kernel mode and can be classified as regular or special. As will become evident later in this article, when APCs are delivered to a particular thread, special kernel-mode APCs don't require permission from that thread to run, whereas regular kernel-mode APCs require that certain conditions hold before they are successfully executed. Besides, special kernel-mode APCs can only be blocked when running at raised IRQL, and they can preempt the execution of a regular kernel-mode APC.
Every APC waiting to execute resides in a thread-specific, kernel-managed queue and every thread in the system contains two APC queues, one for user-mode APCs and another for kernel-mode APCs.
NT represents an APC by a kernel control object named "KAPC." Although the DDK doesn't explicitly document APCs, the KAPC object is clearly declared in NTDDK.H as shown in Listing 1. From this declaration of the KAPC object, the self-explanatory fields are Type and Size. The Type field identifies this kernel object as an APC. In NT, every kernel or executive object is tagged with a type so that functions can ensure they are handed the appropriate object type. Size contains a word-aligned value that indicates the length in bytes that this structure takes up in memory. Spare0 may seem a little obscure, but it's not used for anything meaningful except for memory-alignment reasons. The other field's descriptions are less obvious and I'll explain them throughout the following sections.
APC Environments
At any time during its execution, provided that the current IRQL is at Passive Level, a thread may need to temporarily execute code in another process context. To perform this operation, a thread typically calls the system function KeAttachProcess. On return from this call, the thread is executing within the address space of another process. Any APCs previously waiting to execute in the thread's owning-process context cannot be delivered at this time because the owning-process address space is not currently available. However, new APCs can be perfectly targeted at this thread to execute in the new process address space. Even new APCs can be targeted at this thread to execute in the thread's owning-process context when it finally detaches itself from the new process.
To achieve this degree of control over APC delivery, NT maintains two APC environments or states per thread. Each APC environment contains the APC queues for user-mode and kernel-mode APCs, a pointer to the current process object, and three control variables that indicate: whether there is any pending kernel-mode APCs (KernelApcPending), whether there are any regular kernel-mode APC in progress (KernelApcInProgress), and whether there is a user-mode APC pending (UserApcPending). The locations of these APC environments are kept in an array of two pointers at the ApcStatePointer field in a thread object.
The main APC environment is the one located at the ApcState field in a thread object. APCs waiting to execute in the thread's current process context (whatever it is) reside in the ApcState's queues. Whenever the NT's APC dispatcher and other system components query a thread for pending APCs, they check the main APC environment and, in case there are any, they are delivered at this moment or at some later time, modifying its control variables accordingly. The second APC environment is located at the SavedApcState field in a thread object and is used as a backup place for the main APC environment while a thread is temporarily attached to another process.
The first element in ApcStatePointer always points to the APC environment used for the thread's owning-process context, while the second element points to the APC environment used for the thread's new process context, in case the thread is attached to another process. For example, if a thread is running in its owning-process address space, the first element of the ApcStatePointer array contains the address of ApcState and the second element the address of SavedApcState (in this case SavedApcState is empty). The ApcStateIndex field of the thread object contains the value OriginalApcEnvironment, indicating the thread is running in its owning-process context.
When a thread calls KeAttachProcess to execute subsequent code in another process context, the content of ApcState is copied to SavedApcState. Next, ApcState is cleaned up, its APC queues are reinitialized, its control variables set to zero, and the current process field is set to the new process. These steps successfully guarantee that any APCs previously waiting to execute within the thread's owning-process address space are not delivered while the thread is running in a different process context. Next, the thread's ApcStateIndex field is set to AttachedApcEnvironment, indicating the thread is executing in a different process context. Later, the ApcStatePointer array content is updated to reflect the new state, having its first element point to SavedApcState and its second element to ApcState, indicating that the APC environment for the thread's owning-process context is now located at SavedApcState, and the one for the thread's new process context at ApcState. Finally, the current process context is switched for that of the new process.
What determines the target APC environment for an APC object is the ApcStateIndex field. The value of ApcStateIndex is taken as an index into ApcStatePointer to obtain a pointer to the target APC environment. Later, this pointer is used to place the APC object in its corresponding queue within the APC environment.
When the thread is detaching from the new process (KeDetachProcess), any pending kernel APCs waiting to execute in the new process address space are delivered. Next, the content of SavedApcState is copied back to ApcState, SavedApcState is cleaned up, the thread's ApcStateIndex field is set to OriginalApcEnvironment, and ApcStatePointer is also updated; then the current process context is switched for that of the thread's owning process.
Using APCs
Device drivers use two major functions to utilize APCs. The first, KeInitializeApc (see Listing 2), is used to initialize an APC object. This function takes a driver-allocated APC object, a pointer to the target thread object, the APC environment index (which APC environment to place the APC object in), the APC's kernel, rundown and normal routines pointers, the kind of APC (user mode or kernel mode), and a context parameter.
KeInitializeApc first sets the Type and Size fields to the appropriate values for an APC object. Then it checks the value of the Environment argument. If it is CurrentApcEnvironment, the ApcStateIndex field is set to the target thread's ApcStateIndex field; otherwise, the ApcStateIndex field is set to the value of Environment. Next, this function sets the Thread, RundownRoutine, and KernelRoutine fields directly from the function arguments. To accurately determine the kind of APC, KeInitializeApc checks the value of the NormalRoutine parameter. If it is NULL, the ApcMode field is set to KernelMode and NormalContext is set to NULL. If NormalRoutine is nonNULL, in which case it must point to a valid routine, the ApcMode and NormalContext fields are obtained from the function arguments. Finally, KeInitializeApc sets the Inserted field to FALSE, indicating the APC object has not been placed in its corresponding APC queue yet.
From this explanation, you can easily realize that APC objects missing a valid NormalRoutine are considered as kernel APCs. Specifically, they are considered as special kernel-mode APCs. Indeed, this is the kind of APC the I/O Manager uses to perform asynchronous I/O completion. Conversely, APC objects that define a valid NormalRoutine are considered regular kernel-mode APCs, given that ApcMode is KernelMode; otherwise, they are considered user-mode APCs. The prototypes for KernelRoutine, RundownRoutine, and NormalRoutine are defined in NTDDK.H as shown in Listing 3.
In general, every APC object must contain a valid KernelRoutine function pointer, whatever its kind. This driver-defined routine will be the first one to run when the APC is successfully delivered and executed by the NT's APC dispatcher. User-mode APCs must also contain a valid NormalRoutine function pointer, which must reside in user memory. Likewise, regular kernel-mode APCs contain a valid NormalRoutine, which runs in kernel mode just like KernelRoutine. Optionally, either kind of APC may define a valid RundownRoutine. This routine must reside in kernel memory and is only called when the system needs to discard the contents of the APC queues, such as when the thread exits. In this case, neither KernelRoutine nor NormalRoutine are executed, just the RundownRoutine. An APC without such a routine will be deleted.
Keep in mind that the action of delivering APCs to a thread only involves calling the APC dispatcher subroutine KiDeliverApc at operating system well-defined points, while executing an APC involves actually calling the APC routines.
Once the APC object is completely initialized, device drivers typically call KeInsertQueueApc (see Listing 4) to place the APC object in the target thread's corresponding APC queue. This function takes a pointer to the APC object initialized with KeInitializeApc, two system arguments, and a priority increment. As well as the context parameter passed to KeInitializeApc, these system arguments are simply passed to the APC's routines when they are executed (see Listing 3).
Before KeInsertQueueApc places the APC object in the target thread's corresponding APC queue, it first checks whether the target thread is APC queueable. If it isn't, the function returns immediately with a FALSE result. If APCs can be queued to the thread, the function sets the SystemArgument1 and SystemArgument2 fields directly from the function arguments. Next, the function calls KiInsertQueueApc to actually place the APC object in its corresponding APC queue.
KiInsertQueueApc only takes an APC object and a priority increment, which is applied in case the APC causes the target thread's wait state to be satisfied. This function first obtains the thread's APC queue spinlock and holds it while it is running to prevent other threads from simultaneously modifying the thread's APC structures (note that on uniprocessor systems, KiAcquireSpinLock just returns to the caller). Next, it checks the Inserted field. If it is TRUE, this indicates the APC object has already been placed in one APC queue and the function returns immediately with a FALSE result. If it is FALSE, the function determines the target APC environment from the ApcStateIndex field as explained earlier and proceeds to place the APC object in its corresponding queue by linking it through the ApcListEntry field. The position in which an APC object is placed is determined by the kind of APC. Specifically, regular kernel-mode and user-mode APCs are placed at the end of their corresponding APC queues. Conversely, a special kernel-mode APC is placed at the front of its particular queue before the first regular kernel-mode APC, if there is any already in the queue. If the APC is a kernel-defined user APC used when a thread exits, it's also placed at the front of its corresponding queue and the thread's main APC environment's UserApcPending control variable is set to TRUE. Now, KiInsertQueueApc sets the Inserted field to TRUE, indicating the APC object is already placed in its corresponding queue. Next, a check is performed to see whether the APC was queued to the APC environment for the thread's current process context. If not, the function immediately returns with a TRUE result. If this is a kernel APC (whatever its kind), the KernelApcPending control variable in the thread's main APC environment is set to TRUE.
In the couple-of-sentences allusion to APCs in the Win32 SDK documentation, it's stated that after an APC has been successfully placed in its queue, a software interrupt is issued and the APC is executed the next time the thread is scheduled to run. However, this is not entirely true. Such a software interrupt is only issued if the APC is directed at the calling thread and it's a kernel-mode APC, whether regular or special. Later the function returns with a TRUE result. If the APC is not directed at the calling thread, the target thread is in a wait state at Passive Level; this is a regular kernel-mode APC; the thread is not inside a critical region; and no other regular kernel-mode APC is still in progress, then the thread is awakened with the completion status STATUS_KERNEL_APC, but the wait state is not aborted. If this is a user-mode APC, KiInsertQueueApc checks to see whether the target thread is in an alertable wait state with WaitMode equal to UserMode. If it is, the main APC state's UserApcPending control variable is set to TRUE and the wait state is satisfied with the completion status STATUS_USER_APC. Finally, the function releases the spinlock and returns a TRUE result to indicate the APC object has been successfully queued.
As a supplement to the APC management functions described earlier, device drivers can use the undocumented system service NtQueueApcThread (see Listing 5) to directly queue a user-mode APC to a particular thread. Internally, this function calls KeInitializeApc and KeInsertQueueApc to accomplish this task.
NT's APC Dispatcher
At well-defined points, NT checks whether a thread has pending APCs. Then, the APC dispatcher subroutine KiDeliverApc is executed in the thread's context to initiate APC delivery to the thread. Note that this behavior interrupts the thread's normal execution flow, giving control to the APC dispatcher first and later resuming the thread execution when KiDeliverApc completes.
For example, whenever a thread is scheduled to run, the last step of the context swapping function SwapContext is to inspect whether the new thread has "pending kernel APCs." If so, SwapContext either (1) requests an APC Level software interrupt to initiate APC delivery as soon as the new thread runs at low IRQL (Passive Level) or (2) returns with a TRUE result indicating that the new thread has "pending kernel APCs." This decision is based upon the IRQL at which the new thread will ultimately run when control passes to its restored program counter. If it is higher than Passive Level, SwapContext makes decision (1), and if it is Passive Level, the function makes decision (2).
The return value of SwapContext is only usable by certain system functions that explicitly call SwapContext to force a context switch to another thread. Then, when these system functions are resumed at some later time (when they are rescheduled again), they usually check the return value of SwapContext and if it is TRUE, they call the APC dispatcher to deliver kernel APCs to the current thread. For example, the system function KiSwapThread is used by wait services to relinquish the processor until the wait is satisfied. This function calls SwapContext internally and, when its execution is resumed at the point after the call to SwapContext (when the wait is satisfied), a check is performed on SwapContext's return value. If it is TRUE, KiSwapThread lowers the IRQL to APC Level and calls KiDeliverApc to deliver kernel APCs to the current thread.
For user APCs, the kernel invokes the APC dispatcher only "whenever" a thread is returning to user mode and the thread's main APC environment's UserApcPending control variable is TRUE. For example, when the system service dispatcher KiSystemService is about to return to user mode after completing a system service request, it checks whether there are pending user APCs. If so, it raises the IRQL to APC Level and invokes the APC dispatcher, indicating it should deliver any pending user APCs. Upon execution, KiDeliverApc calls this user APC's KernelRoutine. Later, the helper function KiInitializeUserApc is called to set up the thread's trap frame so that on exit from kernel mode, the thread starts executing in the user-mode APC dispatcher subroutine KiUserApcDispatcher in Ntdll.dll. The helper function's job is to copy the thread's previous execution state (which is stored in the trap frame created in the thread's kernel stack when it entered kernel mode) to the thread's user-mode stack, as well as the APC's normal routine address, normal context, and both system arguments, modifying the trap frame's ESP register accordingly. Finally, it loads the trap frame's EIP register with the address of KiUserApcDispatcher in Ntdll.dll. When the trap frame is eventually dismissed and the kernel transfers control to KiUserApcDispatcher, this function invokes the APC's NormalRoutine, which address and arguments reside in the stack and, when the routine completes, it calls NtContinue to resume the thread execution as if nothing had happened using the previous execution context also in the stack.
Listing 6 shows the pseudocode for the NT's APC dispatcher subroutine KiDeliverApc. As you can observe, its implementation is quite trivial. When the kernel invokes KiDeliverApc to deliver a user-mode APC, PreviousMode is passed as UserMode. TrapFrame points to the thread's trap frame and when it's invoked for kernel APCs, PreviousMode is passed as KernelMode and TrapFrame as NULL.
Note that whenever KernelRoutine is called (whatever the kind of APC), the pointers passed to it are from local copies of the APC's attributes and, because the APC object has already been pulled off its queue, it's safe to free the memory allocated for the APC in KernelRoutine. Besides, this routine has a last chance to modify its arguments before they are passed on to other routines.
Conclusion
APCs provide a very useful mechanism to execute code asynchronously in a particular thread context. As a device driver writer, you can rely on APCs to execute a routine in a particular thread context without that thread's intervention or consent whenever no guarantee of its address space's availability can be made. In this case, special kernel-mode APCs should be used given the restrictions imposed on regular kernel-mode APC delivery. For user application programmers, user-mode APCs can effectively be used to implement some sort of callback notification mechanism.
//-------------------------------------------------------------------------------------------------------
几个函数声明和结构定义:
typedef struct _KAPC { CSHORT Type; CSHORT Size; ULONG Spare0; struct _KTHREAD *Thread; LIST_ENTRY ApcListEntry; PKKERNEL_ROUTINE KernelRoutine; PKRUNDOWN_ROUTINE RundownRoutine; PKNORMAL_ROUTINE NormalRoutine; PVOID NormalContext; // // N.B. The following two members MUST be together. // PVOID SystemArgument1; PVOID SystemArgument2; CCHAR ApcStateIndex; KPROCESSOR_MODE ApcMode; BOOLEAN Inserted; } KAPC, *PKAPC, *RESTRICTED_POINTER PRKAPC; //------
NTKERNELAPI VOID KeInitializeApc ( IN PRKAPC Apc, IN PKTHREAD Thread, IN KAPC_ENVIRONMENT Environment, IN PKKERNEL_ROUTINE KernelRoutine, IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL, IN PKNORMAL_ROUTINE NormalRoutine OPTIONAL, IN KPROCESSOR_MODE ApcMode, IN PVOID NormalContext );
typedef enum _KAPC_ENVIRONMENT { OriginalApcEnvironment, AttachedApcEnvironment, CurrentApcEnvironment } KAPC_ENVIRONMENT; //------------
typedef VOID (*PKKERNEL_ROUTINE) ( IN struct _KAPC *Apc, IN OUT PKNORMAL_ROUTINE *NormalRoutine, IN OUT PVOID *NormalContext, IN OUT PVOID *SystemArgument1, IN OUT PVOID *SystemArgument2 );
typedef VOID (*PKRUNDOWN_ROUTINE) ( IN struct _KAPC *Apc );
typedef VOID (*PKNORMAL_ROUTINE) ( IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ); //------------------
NTKERNELAPI BOOLEAN KeInsertQueueApc ( IN PRKAPC Apc, IN PVOID SystemArgument1, IN PVOID SystemArgument2, IN KPRIORITY Increment ); //-----------------
NTSYSAPI NTSTATUS NTAPI NtQueueApcThread ( IN HANDLE Thread, IN PKNORMAL_ROUTINE NormalRoutine, IN PVOID NormalContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 );
相关推荐
目标检测——布匹缺陷检测数据集
结构瑕疵指的是布料本身的缺陷,包括嵌结、抽纱、错纱、断纱、预缩等问题,这些问题通常是在布料生产过程中出现的。而质量瑕疵则是指布料在使用过程中出现的问题,如污渍、断裂、鼓囊、针眼等,这些问题可能由生产过程中的结构瑕疵导致,也可能是在运输、存放和使用过程中引起的。布匹瑕疵如缺纬、断纬、粗纬、松纬、缺经、断经、粗经、筘痕、污点、破损等,若未得到及时有效的检测,这些瑕疵产品可能会流向市场,导致消费者的不满和退货,严重影响企业的声誉和品牌形象。织疵包括缺经、缺纬、跳花、弓纱、错纱、厚薄段、油污渍等;
APC机制
APC(Asynchronous Procedure Call)异步过程调用。NtQueueApcThread()这个系统调用把一个”用户APC请求”挂入目标线程的APC队列。KTHREAD数据结构中APCState指向线程的APC队列(用户APC和内核APC。 一般来说,只有把APC请求挂入队列,就不再需要触发,而只是等待执行的时机。对于用户APC请求,该时机同样也是目标线程从
CH340驱动安装全攻略:从Windows到MacOS的避坑指南(2025最新版)
本文提供2025年最新版CH340驱动安装全攻略,涵盖Windows、MacOS和Linux三大操作系统。详细解析了驱动安装的核心原理、标准流程,并针对Windows设备管理器报错、MacOS系统安全限制等常见“坑点”提供了深度排错与解决方案,旨在帮助开发者快速稳定地完成USB转串口通信配置。
探索隐蔽代码注入:NtQueueApcThreadEx NTDLL Gadget Injection
探索隐蔽代码注入:NtQueueApcThreadEx NTDLL Gadget Injection ntqueueapcthreadex-ntdll-gadget-injectionThis novel way of using NtQueueApcThreadEx by abusing the ApcRoutine and SystemArgument[0-3] parameters by ...
遥感常用相关指数和计算方法(植被指数/水体指数/雪和冰指数/矿物指数/地表温度指数/云和阴影指数/农业指数)
遥感常用相关指数和计算方法(植被指数/水体指数/雪和冰指数/矿物指数/地表温度指数/云和阴影指数/农业指数)
光学仿真案例(4) 基于纳米微粒激发平面波的米氏散射FDTD仿真模拟
本案例展示了一个基于纳米粒子激发平面波的米氏散射仿真模型(mie scattering),计算其散射和吸收截面、局域场增强和远场散射分布,同时将截面和远场结果与解析解进行了比较,验证了仿真模拟的准确性。
APC
0
AWS SQS跨账户访问失败排查指南
在使用AWS SQS(Simple Queue Service)时,跨账户访问是常见的业务场景。例如,账户A的应用程序向队列发送消息,账户B的消费者从队列拉取消息。尽管AWS官方文档明确支持此类配置,但在实际应用中,由于权限模型的复杂性,开发者和运维人员常会遇到“策略已配置但无法接收消息”的问题。通过本文的逐步排查指南,您不仅可以解决当前问题,还能深入理解AWS跨账户访问的权限模型。接收方账户的用户或角色必须同时附加IAM策略,显式授权操作目标队列。尽管策略看似允许接收方操作,实际测试中却返回空消息或。
关于APC机制
在病毒、逆向中,关于APC最常见的应用就是APC注入的使用了,但是随着随APC的深入了解,发现不管是在内核状态进行APC注入的操作,还是在用户空间执行APC注入的操作。虽然调用的API不同,但是核心内容是不变的,就是往APC队列中插入回调函数,但是一直对于这个回调函数什么时候执行,是怎么执行的很费解.看了毛教授的文章《Windows的APC机制》受益匪浅,总结一点自己关于APC的思路: 之前在分析rootkit的时候,有注意到关于内核中文件的读写函数的API调用中存在APCRoutine的参数设定,内核文件
(功能安全六)硬件FMEDA计算
FMEDA(故障模式、影响与诊断分析)是功能安全验证的核心方法,通过量化分析硬件故障模式及其影响,计算SPFM、LFM、PMHF等关键指标。分析过程包含六大步骤:计算元器件失效率、识别故障模式、评估安全机制诊断覆盖率、分类计算各类失效率、量化指标计算及设计优化。输入需要系统架构图、硬件故障模式清单等资料,输出安全指标达标情况及改进建议,确保设计满足ASIL等级要求。该方法通过系统化的故障分类和量化评估,为硬件安全设计提供科学依据。
柑橘病虫害识别方案总结
1. 方案一 1.1 赛题背景 1.2 数据分析 1.3 模型设计 1.3.1 模型具体方案 1.3.2 模型设计 1.4 实验结果 1.5 总结与展望 2. 方案二 2.1 赛题介绍 2.2 数据分析 2.3 算法方案解析 2.3.1 检测模型 2.3.2 提升策略 2.4 优化思路 3. 方案三 3.1 数据分析 3.1.1 数据说明 3.2 技术展示 3.2.1 数据输入端 3.2.2 模型结构端 3.2.3 上下文信息 3.2.4 训练优化端 3.2.5 创新性分析 3.3 算法及系统思考.....
NtQueueApcThreadEx NTDLL Gadget Injection 项目教程
NtQueueApcThreadEx NTDLL Gadget Injection 项目教程 1. 项目的目录结构及介绍 ntqueueapcthreadex-ntdll-gadget-injection/ ├── src/ │ ├── main.c │ ├── utils.c │ └── ... ├── LICENSE.txt ├── README.md └── ... src/...
DCDC电路断电时放电波形发生震荡和电压跳变问题,如何解决?
DCDC电路断电时放电波形发生震荡和电压跳变问题: 做的一个项目需要用单片机ADC采集电压,要让单片机感应到电压降到3.1V开始往FLASH里存数据,单片机2.4V基本上就工作不了,(根据单片机手册的,擦写的时间在40mS在左右)所以3.1V降到2.4V的时间必须要大于40mS岁以上,在单片机VCC处加了一个100nF的电容,理论仿真下来150mS左右发现存不进去,用示波器抓了一下波形,发现放电时震荡很严重,实际3.1V到2.4V时间只有10ms左右,这个肯定存不进去; 请教师傅说是应该时前级DCDC开关电
深入学习APC
0x01 前言 APCs(Asynchronous Procedure Calls), 在NT中,有两种类型的APCs:用户模式和内核模式。用户APCs运行在用户模式下目标线程当前上下文中,并且需要从目标线程得到许可来运行。特别是,用户模式的APCs需要目标线程处在alertable等待状态才能被成功的调度执行。通过调用下面任意一个函数,都可以让线程进入这种状态。这些函数是:KeW...
廖雪峰Python教程[完整版]
廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白
怀旧版电脑GBC模拟器
再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。
线程警惕和APC
在内部,Windows NT内核有时使用线程警惕(thread alert)来唤醒线程。这种方法使用APC(异步过程调用)来唤醒线程去执行某些特殊例程。用于生成警惕和APC的支持例程没有输出给WDM驱动程序开 发者使用。但是,由于DDK文档和头文件中有大量地方引用了这个概念,所以我想在这里谈一下。当某人通过调用KeWaitXxx例程阻塞一个线程时,需要指定一个布尔参数,该参
TMS_WebGMaps_1.9.8.0_Full_Source
TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder
谈谈对APC的一点理解
异步过程调用(APCs) 是NT异步处理体系结构中的一个基础部分,理解了它,对于了解NT怎样操作和执行几个核心的系统操作很有帮助。 1) APCs允许用户程序和系统元件在一个进程的地址空间内某个线程的上下文中执行代码。 2) I/O管理器使用APCs来完成一个线程发起的异
nt!KiInsertQueueApc函数中的KiRequestApcInterrupt到hal!HalRequestSoftwareInterrupt
nt!KiInsertQueueApc函数中的KiRequestApcInterrupt到hal!HalRequestSoftwareInterrupt
内核同步对象(下)
<br />出处:http://hi.baidu.com/wukongafei/blog/item/76766a43a13dc6159213c646.html<br /> 内核互斥对象<br />互斥(mutex)就是互相排斥(mutual exclusion)的简写。内核互斥对象为多个竞争线程串行化访问共享资源提供了一种方法(不一定是最好的方法)。如果互斥对象不被某线程所拥有,则它是信号态,反之则是非信号态。当线程为了获得互斥对象的控制权而调用KeWaitXxx例程时,内核同时也做了一些工作以帮助避免可能
KiRequestDispatchInterrupt宏定义和nt!KiIpiServiceRoutine函数到hal!HalRequestSoftwareInterrupt
KiRequestDispatchInterrupt宏定义和nt!KiIpiServiceRoutine函数到hal!HalRequestSoftwareInterrupt
KeyboardClassServiceCallback调用nt!IopfCompleteRequest产生KAPC的KernelRoutine=nt!IopCompleteRequest非常重要
kbdclass!KeyboardClassServiceCallback调用nt!IopfCompleteRequest产生KAPC的KernelRoutine=nt!IopCompleteRequest非常重要
从win32k!StartDeviceRead函数中的kbdclass!KeyboardClassRead到nt!IopfCompleteRequest到nt!KiDeliverApc--非常重要
从win32k!StartDeviceRead函数中的kbdclass!KeyboardClassRead到nt!IopfCompleteRequest到nt!KiDeliverApc--非常重要
Windows NT 设备驱动程序开发基础(3)
1.3 实现细节 1.3.1 内核代码运行级别 Windows NT为它的内核模式的代码分配了不同的级别。在同一个CPU上,级别低的过程 可以被任何级别更大的过程中断。级别由低到高排列如下: 级别名称 运行于该级别的过程 PASSIVE_LEVEL DriverEntry, Unload, ShutDown, DispatchXxx。 APC_
win32k!xxxDesktopThread线程分析之从nt!KiDeliverApc到win32k!InputApc--重要
win32k!xxxDesktopThread线程分析之从nt!KiDeliverApc到win32k!InputApc--重要
理解和使用NT驱动程序的执行上下文
理解Windows NT驱动程序最重要的概念之一就是驱动程序运行时所处的“执行上下文”。理解并小心地应用这个概念可以帮助你构建更快、更高效的驱动程序。 NT标准内核模式驱动程序编程中的一个重要观念是某个特定的驱动程序函数执行时所处的“上下文”。传统上文件系统开发者最关注这个问题,但所有类型的NT内核模式驱动程序的编写者都能从对执行上下文的深刻理解中获益。小心谨慎地使用执行上下文的概
612



被折叠的 条评论
为什么被折叠?



