定时器的实现
使用IO定時器
IO定時器每隔1s就會觸發一次,從而進入到定時器例程中,如果某個操作是每n秒執行一次(n為正整數)可以考慮在定時器例程中記錄一個計數器大小就為n,每次進入定時器例程中時將計數器減一,當計數器為0時,表示到達n秒,這個時候可以執行操作。IO定時器只適合處理整數秒的情況
在使用IO定時器之前需要對定時器進行初始化,初始化函數為IoInitializeTimer,定義如下:
初始化完成后可以使用IoStartTimer來啟動定時器,使用IoStopTimer來停止定時器,下面是一個例子
#define PAGEDCODE code_seg("PAGE") #define LOCKEDCODE code_seg() #define INITCODE code_seg("INIT")#define PAGEDDATA data_seg("PAGE") #define LOCKEDDATA data_seg() #define INITDATA data_seg("INIT")typedef struct _tag_DEVICE_EXTENSION {PDEVICE_OBJECT DeviceObject;UNICODE_STRING uDeviceName;UNICODE_STRING uSymbolickName;LONG lTimerCount; //定時器觸發時間,以秒為單位 }DEVICE_EXTENSION, *PDEVICE_EXTENSION;NTSTATUS DriverEntry(DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath) {NTSTATUS status;LONG i;PDEVICE_OBJECT pDeviceObject;UNREFERENCED_PARAMETER(RegistryPath);DriverObject->DriverUnload = DriverUnload;//設置派遣函數,這些代碼在這就省略了status = CreateDevice(DriverEntry, &pDeviceObject);IoStartTimer(pDeviceObject);return status; }#pragma LOCKEDCODE VOID IoTimer(DEVICE_OBJECT *DeviceObject,PVOID Context) {LONG ret;PDEVICE_EXTENSION pDeviceExtension;UNICODE_STRING uProcessName;PEPROCESS pCurrProcess;UNREFERENCED_PARAMETER(Context);pDeviceExtension = (PDEVICE_EXTENSION)(DeviceObject->DeviceExtension);ASSERT(NULL != pDeviceExtension);//采用互鎖操作將定時器數減一InterlockedDecrement(&pDeviceExtension->lTimerCount);//判斷當前時間是否到達3秒ret = InterlockedCompareExchange(&pDeviceExtension->lTimerCount, TIME_OUT, 0);if(0 == ret){DbgPrint("3s time out\n");}pCurrProcess = IoGetCurrentProcess();RtlInitUnicodeString(&uProcessName, (PTSTR)((ULONG)pCurrProcess + 0x174));DbgPrint("the current process %wZ", uProcessName); }#pragma INITCODE NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObject,PDEVICE_OBJECT *ppDeviceObject) {NTSTATUS status;UNICODE_STRING uDeviceName;UNICODE_STRING uSymbolickName;PDEVICE_EXTENSION pDeviceExtension;RtlInitUnicodeString(&uDeviceName, DEVICE_NAME);RtlInitUnicodeString(&uSymbolickName, SYMBOLICK_NAME);if(NULL != ppDeviceObject){//創建設備對象并填充設備擴展中的變量...IoInitializeTimer(*ppDeviceObject, IoTimer, NULL);status = IoCreateSymbolicLink(&uSymbolickName, &uDeviceName);if(!NT_SUCCESS(status)){//出錯的話就做一些清理工作...return status;}if(NULL != pDeviceExtension){RtlInitUnicodeString(&pDeviceExtension->uSymbolickName, SYMBOLICK_NAME);}return status;}return STATUS_UNSUCCESSFUL; }需要注意的是IO定時器例程是位于DISPATCH_LEVEL,所以它不能使用分頁內存,所以在函數前加上一句#pragma LOCKEDCODE,表示它在非分頁內存中
DPC定時器
DPC定時器相比IO定時器來說更加靈活,它可以指定任何時間間隔。DPC內部使用KTIMER這個內核對象進行定時,每當時間到達設置的時間,那么系統就會將對應的DPC例程加入到DPC隊列中,當系統讀取DPC隊列時,這個DPC例程就會被執行,使用DPC定時器的步驟一般是:
1. 分別調用KeInitializeTimer和KeInitializeDpc初始化KTIMER對象和DPC對象
2. 用KeSetTimer開啟定時器
3. 在DPC例程中再次調用KeSetTimer開啟定時器
4. 調用KeCancelTimer關閉定時器
由于每次執行KeSetTimer都只會觸發一次DPC例程,所以如果想要周期性的調用DPC例程,需要在DPC例程中再次調用KeSetTimer。
這些函數的定義如下:
下面是一個使用的例子
typedef struct _tag_DEVICE_EXTENSION {PDEVICE_OBJECT pDeviceObj;UNICODE_STRING uDeviceName;UNICODE_STRING uSymbolickName;KTIMER timer;KDPC Dpc; }DEVICE_EXTENSION, *PDEVICE_EXTENSION;NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) {PDEVICE_EXTENSION pDeviceExtension;PDEVICE_OBJECT pDeviceObj;int i;NTSTATUS status;LARGE_INTEGER time_out;UNREFERENCED_PARAMETER(pRegistryPath);pDriverObject->DriverUnload = DriverUnload;//設置派遣函數...status = CreateDevice(pDriverObject, &pDeviceObj);//失敗處理...//設置定時器time_out.QuadPart = -1 * 10000000; //1s = 1000000000nsstatus = KeSetTimer(&pDeviceExtension->timer,time_out, &pDeviceExtension->Dpc);return STATUS_SUCCESS; }VOID DriverUnload(PDRIVER_OBJECT pDriverObject) {//該函數主要用來清理相關資源... }NTSTATUS DefauleDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {//默認返回成功 }NTSTATUS CreateDevice(PDRIVER_OBJECT pDriverObj, PDEVICE_OBJECT *ppDeviceObj) {PDEVICE_EXTENSION pDevEx;PDEVICE_OBJECT pDevObj;UNICODE_STRING uDeviceName;UNICODE_STRING uSymbolicName;NTSTATUS status;//創建設備對象,填充擴展設備內容...//初始化KTIMER DPCKeInitializeTimer(&pDevEx->timer);KeInitializeDpc(&pDevEx->Dpc, TimerDpc, pDevObj);//設置連接符號...return STATUS_SUCCESS; }VOID TimerDpc(__in struct _KDPC *Dpc,__in_opt PVOID DeferredContext,__in_opt PVOID SystemArgument1,__in_opt PVOID SystemArgument2) {static int i = 0;PTSTR pProcessName;PEPROCESS pEprocess;LARGE_INTEGER time_out;PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)DeferredContext;PDEVICE_EXTENSION pDevEx = (PDEVICE_EXTENSION)(pDevObj->DeviceExtension);ASSERT(NULL != pDevObj);pEprocess = PsGetCurrentProcess();pProcessName = (PTSTR)((ULONG)pEprocess + 0x174);DbgPrint("%d Call TimerDpc, Process: %s\n", i, pProcessName);time_out.QuadPart = -1 * 10000000; //1s = 1000000000nsKeSetTimer(&pDevEx->timer, time_out, &pDevEx->Dpc);i++; }轉載于:https://www.cnblogs.com/lanuage/p/7725710.html
總結
- 上一篇: Python if条件判断
- 下一篇: codevs 2924 数独挑战