Windows内核编程中的KeGenericCallDpc函数

Windows内核编程中的KeGenericCallDpc函数

KeGenericCallDpc 是 Windows 内核中一个强大但未公开文档化(Undocumented) 的函数。它的核心作用是向系统上的每一个逻辑处理器(CPU核心)广播一个延迟过程调用(DPC),让指定的回调函数在每个CPU核心上都执行一次。

函数声明

c 复制代码
//
// 注意:WDK 10.0.28000.0 的 km 头文件中缺少 KeGenericCallDpc 的声明
//(SDK 头文件缺陷),但该 API 仍由 ntoskrnl 正常导出。
// 此处补充与官方 WDK 签名一致的 extern 声明以通过编译;
// 未来若头文件恢复声明,重复的函数声明在 C++ 中合法,不影响编译。
//
extern "C"
NTKERNELAPI
BOOLEAN
KeGenericCallDpc(
	_In_ PKDEFERRED_ROUTINE Routine,
	_In_opt_ PVOID Context
);

工作原理

如何广播DPC

  1. 获取处理器数量:函数内部会调用 KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS) 来获取当前系统中所有活跃逻辑处理器的数量。
  2. 为每个CPU调度DPC:它会为每一个逻辑处理器分别初始化并插入一个DPC。当这些DPC在各自的CPU核心上被调度执行时,Routine 回调函数就会被调用。
  3. 并行执行:回调函数会在所有CPU上几乎同时、并行地运行。

同步机制

由于回调函数在所有CPU上并行执行,调用 KeGenericCallDpc 的原始线程需要一种方法来等待所有CPU上的工作完成。为此,必须配合使用另外两个同样未公开文档化的函数:

  • KeSignalCallDpcSynchronize:在你的回调函数(Routine)中,必须在某个时刻调用此函数。它的作用是在所有处理器之间建立一个同步屏障(Barrier),确保所有并发的回调执行到此处时能进行同步。
  • KeSignalCallDpcDone:在所有回调函数都完成了必要的同步工作后,再由原始调用线程调用此函数。它用于向原始线程发出信号,表明所有CPU上的DPC均已处理完毕。

一个典型的使用流程如下:

  1. 调用 KeGenericCallDpc 广播DPC。
  2. 在每个CPU的回调函数中,执行核心任务后,调用 KeSignalCallDpcSynchronize。
  3. 当所有CPU都调用了 KeSignalCallDpcSynchronize 后,原始调用线程可以调用 KeSignalCallDpcDone。
  4. 此时,原始线程可以安全地继续执行,因为所有CPU上的工作都已完成。

注意事项

回调函数在DPC级别(IRQL = DISPATCH_LEVEL) 运行,这要求代码必须位于非分页内存(Non-paged pool) 中,并且不能执行任何可能导致阻塞或等待的操作。

总的来说,KeGenericCallDpc 是一个强大但危险性极高的内核工具。鉴于其未公开和不稳定的特性,在开发生产级驱动程序时强烈不建议使用。如果确实有需求,应优先考虑使用其公开的替代方案 KeIpiGenericCall。

相关推荐
阿昭L21 天前
ZwQuerySystemInformation通过PsLoadedModuleList枚举内核模块
windows·逆向工程·windows内核
阿昭L1 个月前
记一次符号类型不一致导致的链接错误
windows内核
阿昭L1 个月前
Windows对象句柄回调 (Object Handle Callbacks)
windows内核
阿昭L3 个月前
Windows内核事件通知机制
windows·windows内核
阿昭L3 个月前
通过KiSystemServiceUser获取SSDT基址
逆向工程·windows内核·ssdt
阿昭L3 个月前
Windows键盘过滤
windows·驱动开发·windows内核·过滤驱动
阿昭L3 个月前
通过cr3读写进程内存
保护模式·windows内核
阿昭L3 个月前
调试CreateProcess
windows·进程·逆向工程·windows内核
阿昭L4 个月前
调试Windows11启动过程
windows·uefi·windows内核