(十七)、定时器
一、IO定时器
IoInitializeTimer
IoStartTimer
代码
#include <ntddk.h> VOID Unload(PDRIVER_OBJECT driver) { IoStopTimer(driver->DeviceObject); DbgPrint("Driver Unload\n"); } VOID IoTimer( PDEVICE_OBJECT pDeviceObject, PVOID pContext ) { DbgPrint("iO定时器\n"); } NTSTATUS DriverEntry(PDRIVER_OBJECT driver) { DbgPrint("Driver Load\n"); PDEVICE_OBJECT DeviceObject; NTSTATUS status; status = IoCreateDevice(driver, 0, NULL, FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("设备创建失败\n"); return status; } IoInitializeTimer(DeviceObject, IoTimer, NULL); IoStartTimer(DeviceObject);//启动定时器,默认1s一次// driver->DriverUnload = Unload; return STATUS_SUCCESS; }
1s 1次,直至驱动卸载
二、DPC定时器
DPC计时器精度比较高,精确到微秒
KeSetTimer
KeInitializeDpc
代码
#include <ntddk.h> KDPC dpc; KTIMER timer; LARGE_INTEGER timeout; VOID Unload(PDRIVER_OBJECT driver) { //IoStopTimer(driver->DeviceObject); KeCancelTimer(&timer); DbgPrint("Driver Unload\n"); IoDeleteDevice(driver->DeviceObject); } VOID IoTimer( PDEVICE_OBJECT pDeviceObject, PVOID pContext ) { DbgPrint("iO定时器\n"); } void DpcRoutine( struct _KDPC* Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2 ) { DbgPrint("Dpc Timer\n"); KeSetTimer(&timer, timeout, &dpc); } NTSTATUS DriverEntry(PDRIVER_OBJECT driver) { DbgPrint("Driver Load\n"); PDEVICE_OBJECT DeviceObject; NTSTATUS status; status = IoCreateDevice(driver, 0, NULL, FILE_DEVICE_UNKNOWN, FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("设备创建失败\n"); return status; } //IoInitializeTimer(DeviceObject, IoTimer, NULL); //IoStartTimer(DeviceObject);//启动定时器,默认1s一次// timeout = RtlConvertLongToLargeInteger(-10 * 100 * 1000);//100 ms 一次// KeInitializeTimer(&timer); KeInitializeDpc(&dpc, DpcRoutine, NULL); driver->DriverUnload = Unload; KeSetTimer(&timer, timeout, &dpc); return STATUS_SUCCESS; }
每100ms触发一次
三、等待
KeWaitForSingleObject :等待事件或对象
KeStallExecutionProcessor:CPU空转
代码
#include <ntddk.h> VOID Unload(PDRIVER_OBJECT driver) { DbgPrint("Driver Unload\n"); } void WaitTest1() { KEVENT Event; LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10 * 1000 * 1000); KeInitializeEvent(&Event, SynchronizationEvent,FALSE); KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &timeout); DbgPrint("等待结束\n"); } void WaitTest2() { KTIMER timer; LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10 * 1000 * 1000); KeInitializeTimer(&timer); KeSetTimer(&timer, timeout, NULL); KeWaitForSingleObject(&timer, Executive, KernelMode, FALSE, &timeout); DbgPrint("等待结束2"); } void WaitTest3() { LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10 * 1000 * 1000); KeDelayExecutionThread(KernelMode, FALSE, &timeout); DbgPrint("等待结束3\n"); } void WaitTest4() { KeStallExecutionProcessor(1000 * 1000); DbgPrint("等待结束4\n"); } NTSTATUS DriverEntry(PDRIVER_OBJECT driver) { DbgPrint("Driver Load\n"); WaitTest1(); WaitTest2(); WaitTest3(); WaitTest4(); driver->DriverUnload = Unload; return STATUS_SUCCESS; }
四、时间函数与Irp超时处理
KeQuerySystemTime
查询系统时间
ExSystemTimeToLocalTime
RtlTimeToTimeFields
#include <ntddk.h> VOID Unload(PDRIVER_OBJECT driver) { DbgPrint("Driver Unload\n"); } void WaitTest1() { KEVENT Event; LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10 * 1000 * 1000); KeInitializeEvent(&Event, SynchronizationEvent,FALSE); KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &timeout); DbgPrint("等待结束\n"); } void WaitTest2() { KTIMER timer; LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10 * 1000 * 1000); KeInitializeTimer(&timer); KeSetTimer(&timer, timeout, NULL); KeWaitForSingleObject(&timer, Executive, KernelMode, FALSE, &timeout); DbgPrint("等待结束2"); } void WaitTest3() { LARGE_INTEGER timeout = RtlConvertLongToLargeInteger(-10 * 1000 * 1000); KeDelayExecutionThread(KernelMode, FALSE, &timeout); DbgPrint("等待结束3\n"); } void WaitTest4() { KeStallExecutionProcessor(1000 * 1000); DbgPrint("等待结束4\n"); } VOID FunTime() { LARGE_INTEGER systemtime; LARGE_INTEGER localtime; TIME_FIELDS timefields; KeQuerySystemTime(&systemtime);//查询系统时间// ExSystemTimeToLocalTime(&systemtime, &localtime); RtlTimeToTimeFields(&localtime, &timefields); DbgPrint("%d年%d月%d日 %d:%d:%d %.3d\n", timefields.Year, timefields.Month, timefields.Day, timefields.Hour, timefields.Minute, timefields.Second, timefields.Milliseconds); } NTSTATUS DriverEntry(PDRIVER_OBJECT driver) { DbgPrint("Driver Load\n"); /*WaitTest1(); WaitTest2(); WaitTest3(); WaitTest4();*/ FunTime(); driver->DriverUnload = Unload; return STATUS_SUCCESS; }
五、Irp超时处理
0环代码
#include <ntddk.h> KDPC dpc; KTIMER timer; LARGE_INTEGER timeout; VOID Unload(PDRIVER_OBJECT driver) { //IoStopTimer(driver->DeviceObject); UNICODE_STRING SymbolicName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); KeCancelTimer(&timer); DbgPrint("Driver Unload\n"); IoDeleteSymbolicLink(&SymbolicName); IoDeleteDevice(driver->DeviceObject); DbgPrint("driver unload\n"); } VOID IoTimer( PDEVICE_OBJECT pDeviceObject, PVOID pContext ) { DbgPrint("iO定时器\n"); } void DpcRoutine( struct _KDPC* Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2 ) { PIRP Irp = (PIRP)DeferredContext; Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); DbgPrint("Dpc Timer\n"); } NTSTATUS DispatchRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp) { Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DispatchRead(PDEVICE_OBJECT DeviceObject, PIRP Irp) { IoMarkIrpPending(Irp); timeout = RtlConvertLongToLargeInteger(-10 * 2000 * 1000);// 2s 一次// KeInitializeTimer(&timer); KeInitializeDpc(&dpc, DpcRoutine, Irp); KeSetTimer(&timer, timeout, &dpc); return STATUS_PENDING; } NTSTATUS DriverEntry(PDRIVER_OBJECT driver) { DbgPrint("Driver Load\n"); UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\??\\MyDDKLink"); UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\MyDDKName"); PDEVICE_OBJECT DeviceObject; NTSTATUS status; status = IoCreateDevice(driver, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); if (!NT_SUCCESS(status)) { DbgPrint("设备创建失败\n"); return status; } status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); if (!NT_SUCCESS(status)) { DbgPrint("符号链接创建失败\n"); IoDeleteDevice(DeviceObject); return status; } //IoInitializeTimer(DeviceObject, IoTimer, NULL); //IoStartTimer(DeviceObject);//启动定时器,默认1s一次// //timeout = RtlConvertLongToLargeInteger(-10 * 2000 * 1000);// 2s 一次// //KeInitializeTimer(&timer); //KeInitializeDpc(&dpc, DpcRoutine, NULL); //KeSetTimer(&timer, timeout, &dpc); driver->DriverUnload = Unload; driver->MajorFunction[IRP_MJ_CREATE] = DispatchRoutine; driver->MajorFunction[IRP_MJ_CLOSE] = DispatchRoutine; driver->MajorFunction[IRP_MJ_READ] = DispatchRead; DeviceObject->Flags |= DO_BUFFERED_IO; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; //KeSetTimer(&timer, timeout, &dpc); return STATUS_SUCCESS; }
三环代码
// dpc定时器三环代码.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #include <iostream> #include <stdio.h> #include <Windows.h> using namespace std; int main() { DWORD dwRet; HANDLE hDevice = CreateFile(TEXT("\\\\.\\MyDDKLink"), GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL ); if (hDevice == INVALID_HANDLE_VALUE) { printf("设备打开失败 %d \n",GetLastError()); getchar(); return -1; } OVERLAPPED ol = { NULL }; ReadFile(hDevice, NULL, 0, &dwRet, &ol); WaitForSingleObject(ol.hEvent, INFINITE); CloseHandle(hDevice); getchar(); return 0; }
运行两秒后显示 Dpc Timer