日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

定时器的实现

發(fā)布時間:2025/3/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 定时器的实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

使用IO定時器

IO定時器每隔1s就會觸發(fā)一次,從而進入到定時器例程中,如果某個操作是每n秒執(zhí)行一次(n為正整數(shù))可以考慮在定時器例程中記錄一個計數(shù)器大小就為n,每次進入定時器例程中時將計數(shù)器減一,當計數(shù)器為0時,表示到達n秒,這個時候可以執(zhí)行操作。IO定時器只適合處理整數(shù)秒的情況
在使用IO定時器之前需要對定時器進行初始化,初始化函數(shù)為IoInitializeTimer,定義如下:

NTSTATUS IoInitializeTimer(IN PDEVICE_OBJECT DeviceObject, //設備對象指針IN PIO_TIMER_ROUTINE TimerRoutine,//定時器例程IN PVOID Context//傳給定時器例程的函數(shù));

初始化完成后可以使用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; //定時器觸發(fā)時間,以秒為單位 }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;//設置派遣函數(shù),這些代碼在這就省略了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);//采用互鎖操作將定時器數(shù)減一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){//創(chuàng)建設備對象并填充設備擴展中的變量...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,所以它不能使用分頁內存,所以在函數(shù)前加上一句#pragma LOCKEDCODE,表示它在非分頁內存中

DPC定時器

DPC定時器相比IO定時器來說更加靈活,它可以指定任何時間間隔。DPC內部使用KTIMER這個內核對象進行定時,每當時間到達設置的時間,那么系統(tǒng)就會將對應的DPC例程加入到DPC隊列中,當系統(tǒng)讀取DPC隊列時,這個DPC例程就會被執(zhí)行,使用DPC定時器的步驟一般是:
1. 分別調用KeInitializeTimer和KeInitializeDpc初始化KTIMER對象和DPC對象
2. 用KeSetTimer開啟定時器
3. 在DPC例程中再次調用KeSetTimer開啟定時器
4. 調用KeCancelTimer關閉定時器
由于每次執(zhí)行KeSetTimer都只會觸發(fā)一次DPC例程,所以如果想要周期性的調用DPC例程,需要在DPC例程中再次調用KeSetTimer。
這些函數(shù)的定義如下:

VOID KeInitializeDpc(IN PRKDPC Dpc, //DPC對象IN PKDEFERRED_ROUTINE DeferredRoutine, //DPC例程IN PVOID DeferredContext//傳給DPC例程的參數(shù)); BOOLEAN KeSetTimer(IN PKTIMER Timer,//定時器IN LARGE_INTEGER DueTime, //隔多久觸發(fā)這個DPC例程,這個值是正數(shù)則表示從1601年1月1日到觸發(fā)這個DPC例程所經(jīng)歷的時間,為負數(shù),則表示從當前時間,間隔多長時間后觸發(fā),單位為100nsIN PKDPC Dpc OPTIONAL //傳入上面初始化的DPC對象);

下面是一個使用的例子

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;//設置派遣函數(shù)...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) {//該函數(shù)主要用來清理相關資源... }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;//創(chuàng)建設備對象,填充擴展設備內容...//初始化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

總結

以上是生活随笔為你收集整理的定时器的实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。