天天看點

DPC計時器

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;
}
           
DPC計時器

KeInitializeTimer函數分析

DPC計時器

KeInitializeTimerEx函數分析

如下圖,箭頭所指,僅僅是填寫傳入KTIMER對象的字段

DPC計時器

KeInitializeDpc函數分析

DPC計時器

KeInitializeTimer函數分析

DPC計時器

KeSetTimerEx函數分析

DPC計時器
DPC計時器
DPC計時器

32BIT-XP下實驗

繼續閱讀