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下實驗