- 关于内核定时器,及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;
- }