关于内核定时器,及DPC的使用,看来一些代码,这个估计是比较规范的用法了,很基础,希望对新手有帮助
注意,这里的定时器不太精确!
代码:
#include <ntddk.h> typedef struct _DEVICE_EXTENSION { LIST_ENTRY list_head; KSPIN_LOCK list_lock; PVOID thread_pointer; BOOLEAN terminate_thread; KEVENT request_event; KTIMER my_timer; KDPC KiTimerExpireDpc; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; #define dprintf if (DBG) DbgPrint #define nprintf DbgPrint #define DEVICE_NAME L"\\Device\\devhello" // Driver Name #define LINK_NAME L"\\DosDevices\\hello" // Link Name // // The device driver IOCTLs // #define IOCTL_BASE 0x800 #define MY_CTL_CODE(i) \ CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_HELLO MY_CTL_CODE(0) ///////////////////////////////////////////////////////////////////// //函数声明 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString); NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp); NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp); VOID DriverUnload(PDRIVER_OBJECT pDriverObj); NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp); VOID KiTimerExpirationFunction ( IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ); NTSTATUS ThreadFunc ( IN PVOID Context); ///////////////////////////////////////////////////////////////////// NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString ) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING ustrLinkName; UNICODE_STRING ustrDevName; PDEVICE_OBJECT device_object; PDEVICE_EXTENSION device_extension; HANDLE thread_handle; /* 在驱动中是以100纳秒为单位的 1000纳秒=1微秒 1000微秒=1毫秒 1000毫秒=1秒 10*1000*1000 */ LARGE_INTEGER duetime = {0}; #define POLLING_INTERVAL 3000 dprintf("[hello] DriverEntry\n"); pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; pDriverObj->DriverUnload = DriverUnload; RtlInitUnicodeString(&ustrDevName, DEVICE_NAME); status = IoCreateDevice(pDriverObj, sizeof(DEVICE_EXTENSION), &ustrDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &device_object); if(!NT_SUCCESS(status)) { dprintf("[hello] IoCreateDevice = 0x%x\n", status); return status; } RtlInitUnicodeString(&ustrLinkName, LINK_NAME); status = IoCreateSymbolicLink(&ustrLinkName, &ustrDevName); if(!NT_SUCCESS(status)) { dprintf("[hello] IoCreateSymbolicLink = 0x%x\n", status); IoDeleteDevice(device_object); return status; } device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension; InitializeListHead(&device_extension->list_head); KeInitializeSpinLock(&device_extension->list_lock); KeInitializeEvent( &device_extension->request_event, NotificationEvent, FALSE); // KeInitializeTimer(&my_timer);//这是个旧的函数 KeInitializeTimerEx(&device_extension->my_timer, NotificationTimer); // 初始化定时器过期的DPC对象 KeInitializeDpc(&device_extension->KiTimerExpireDpc, (PKDEFERRED_ROUTINE)KiTimerExpirationFunction, (PVOID) device_object); // KeSetTimer(&my_timer,timeout,&KiTimerExpireDpc); 仅仅只能设置一次 // KeSetTimerEx(&my_timer, timeout, period, &KiTimerExpireDpc);这个可以循环设置 KeSetTimerEx(&device_extension->my_timer, duetime, POLLING_INTERVAL, &device_extension->KiTimerExpireDpc); // KeSetTimerEx语句启动周期定时器。由于duetime参数是0, // 所以定时器立即进入信号态。 // 然后每隔POLLING_INTERVAL=3秒触发一次。 device_extension->terminate_thread = FALSE; status = PsCreateSystemThread( &thread_handle, (ACCESS_MASK) 0L, NULL, NULL, NULL, ThreadFunc, device_object ); if (!NT_SUCCESS(status)) { IoDeleteDevice(device_object); return status; } status = ObReferenceObjectByHandle( thread_handle, THREAD_ALL_ACCESS, NULL, KernelMode, &device_extension->thread_pointer, NULL ); if (!NT_SUCCESS(status)) { ZwClose(thread_handle); device_extension->terminate_thread = TRUE;//如果出错就关闭创建的线程 KeSetEvent( &device_extension->request_event, (KPRIORITY) 0, FALSE ); IoDeleteDevice(device_object); return status; } ZwClose(thread_handle); return STATUS_SUCCESS; } VOID KiTimerExpirationFunction ( IN struct _KDPC *Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) { PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)DeferredContext; PDEVICE_EXTENSION device_extension = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; //kesetevent 必需在较低级别用 //ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); //dprintf("level in timer function is %x\n",KeGetCurrentIrql()); dprintf("haha dpc function work\n"); KeSetEvent(&device_extension->request_event, (KPRIORITY) 0, FALSE); }; NTSTATUS ThreadFunc ( IN PVOID Context) { PFILE_OBJECT ConnectionFileObject, AddressFileObject; HANDLE AddressHandle, ConnectionHandle; NTSTATUS Status; IO_STATUS_BLOCK IoStatus; KEVENT Event; PDEVICE_OBJECT device_object; PDEVICE_EXTENSION device_extension; device_object = (PDEVICE_OBJECT) Context; device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension; KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY); //**************************** //**************************** //开始工作 此处用2重循环,你可以添加实际的代码 for (;;) { do { dprintf("thread work ok !!\n"); goto failselabel; } while (TRUE); failselabel: KeWaitForSingleObject( &device_extension->request_event, Executive, KernelMode, FALSE, NULL );//在这儿等 //KeClearEvent(&Event);//清除一下试试 //killvxk 2007-01-31 11:18 //严重提醒不要使用KeClearEvent(&Event); //如果你还要用那个事件就不要用那个Clear,要其它手段~如果你不需要那个event了, //那你应该在thread里判断下~ KeResetEvent(&device_extension->request_event); if ( device_extension->terminate_thread ) { PsTerminateSystemThread(STATUS_SUCCESS); } } dprintf("never be here !\n"); return Status; } VOID DriverUnload( PDRIVER_OBJECT pDriverObj ) { PDEVICE_EXTENSION device_extension; UNICODE_STRING strLink; RtlInitUnicodeString(&strLink, LINK_NAME); device_extension = (PDEVICE_EXTENSION) pDriverObj->DeviceObject->DeviceExtension; //停止创建的线程 if (KeCancelTimer(&device_extension->my_timer) == FALSE) { // KeCancelTimer(&device_extension->my_timer);//取消定时器 dprintf( " no timer active at terminate\n"); } device_extension->terminate_thread = TRUE;//停止线程 KeSetEvent( &device_extension->request_event, (KPRIORITY) 0, FALSE ); KeWaitForSingleObject( device_extension->thread_pointer,//等待线程对象结束,注意哦,是对象 Executive, KernelMode, FALSE, NULL ); ObDereferenceObject(device_extension->thread_pointer); IoDeleteSymbolicLink(&strLink); IoDeleteDevice(pDriverObj->DeviceObject); dprintf("[hello] Unloaded\n"); } NTSTATUS DispatchCreate( PDEVICE_OBJECT pDevObj, PIRP pIrp ) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; dprintf("[hello] IRP_MJ_CREATE\n"); IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DispatchClose( PDEVICE_OBJECT pDevObj, PIRP pIrp ) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; dprintf("[hello] IRP_MJ_CLOSE\n"); IoCompleteRequest(pIrp, IO_NO_INCREMENT); return STATUS_SUCCESS; } NTSTATUS DispatchIoctl( PDEVICE_OBJECT pDevObj, PIRP pIrp ) { NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST; PIO_STACK_LOCATION pIrpStack; ULONG uIoControlCode; PVOID pIoBuffer; ULONG uInSize; ULONG uOutSize; pIrpStack = IoGetCurrentIrpStackLocation(pIrp); uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode; pIoBuffer = pIrp->AssociatedIrp.SystemBuffer; uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength; uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch(uIoControlCode) { case IOCTL_HELLO: { dprintf("[hello] Hello\n"); status = STATUS_SUCCESS; } break; } if(status == STATUS_SUCCESS) pIrp->IoStatus.Information = uOutSize; else pIrp->IoStatus.Information = 0; ///////////////////////////////////// pIrp->IoStatus.Status = status; IoCompleteRequest(pIrp, IO_NO_INCREMENT); return status; }
![](88954/624747/25933.jpg)