DPC计时器

DPC计时器是Windows驱动中用于实现精确时间间隔的内核级技术,不同于IO计时器。主要函数包括KeInitializeTimer、KeInitializeDpc和KeSetTimer。在使用时需要注意KTIMER和KDPC对象的生命周期,必须避免作为局部变量。DPC计时器为一次性触发,需要在DPC回调中重新设置。在驱动卸载时,必须调用KeCancelTimer以防止系统崩溃。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DPC计时器,是除了IO计时器的另一种内核方式的计时器技术,它能实现比IO计时器(秒级别)更加细微级别的时间间隔,

  实现DPC 计时器所需要的函数 KeInitializeTimer,KeInitializeDpc,KeSetTimer

#include <ntddk.h>

KTIMER kTimer = { 0 };
KDPC dpc1 = { 0 };
KDPC dpc2 = { 0 };

VOID DriverUnload(PDRIVER_OBJECT pDriverObj){
	return;
}
VOID SetDueTime(ULONG seconds, PLARGE_INTEGER pAccordingLi){
	LONG  dueTime = -1 * seconds * 1000 * 1000 * 10;
	*pAccordingLi = RtlConvertLongToLargeInteger(dueTime);
}


VOID
MyDeferredRoutine(
_In_ struct _KDPC *Dpc,
_In_opt_ PVOID DeferredContext,
_In_opt_ PVOID SystemArgument1,
_In_opt_ PVOID SystemArgument2
){
	LARGE_INTEGER li = { 0 };
	KdPrint(("this text is  from my DeferedRoutine \n"));
	SetDueTime(10, &li);
	KeSetTimer(&kTimer, li, &dpc2);
	return;
}


VOID DPCTimer(){
	
	KeInitializeTimer(&kTimer);
	KeInitializeDpc(&dpc1, MyDeferredRoutine, NULL);
	KeInitializeDpc(&dpc2, MyDeferredRoutine, NULL);
	LARGE_INTEGER li = { 0 };
	
	SetDueTime(3, &li);
	KeSetTimer(&kTimer,li, &dpc1);

	SetDueTime(10, &li);
	KeSetTimer(&kTimer, li, &dpc2);
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath){
	pDriverObj->DriverUnload = DriverUnload;
	DPCTimer();
	KdPrint(("Enter DPCTimer ...\n"));
	return STATUS_SUCCESS;
}


需要注意的是

1.  KTIMER 对象,KDPC对象的生命周期要长,不能是局部变量的生存周期,因为你创建了这些对象时,不光只有你在使用它,系统也需要在未来操作它,故而,若是在函数中 定义 这些对象,存在于未出函数时的栈中,故而,出函数后其位置的数据会变得不可预料,可认为无效,这时候很有可能造成系统崩溃。

2.它是一次性的,故而你需要在DPC回调函数中再一次调用KeSetTimer并设置相应的时间间隔

3.如我在实例中所写,我 原本的意思是初始化2个DPC,然后绑定到同一个KTIMER,在不同的时间间隔触发,一个3秒后,

一个10秒后,可结果只触发了10秒的,可见前面设定的被后面设定的给摸掉了

4.你卸载驱动时,如我的例子这般,系统会崩溃的,为什么,因为你的DPC 被插入到CPU 的DPC队列时,与其绑定的DPC

回调函数是在你的模块中的,而且,KDPC,KTIMER对象也是在这模块中定义的,卸载后果,可想而知

【解决之道:在DriverUnload中加上KeCancelTimer  调用】

之前:

VOID DPCTimer(){
	
	KeInitializeTimer(&kTimer);
	KeInitializeDpc(&dpc1, MyDeferredRoutine, NULL);
	KeInitializeDpc(&dpc2, MyDeferredRoutine, NULL);
	LARGE_INTEGER li = { 0 };
	
	SetDueTime(3, &li);
	KeSetTimer(&kTimer,li, &dpc1);

	SetDueTime(10, &li);
	KeSetTimer(&kTimer, li, &dpc2);
}


之后:

VOID DriverUnload(PDRIVER_OBJECT pDriverObj){
	KeCancelTimer(&kTimer);//取消定时器
	KeStallExecutionProcessor(5 * 1000 * 1000);//过5秒再退出,留有缓冲余地
	return;
}





KeInitializeTimer函数分析


KeInitializeTimerEx函数分析

如下图,箭头所指,仅仅是填写传入KTIMER对象的字段



KeInitializeDpc函数分析



KeInitializeTimer函数分析



KeSetTimerEx函数分析




32BIT-XP下实验

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值