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