- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
[cpp]view
plaincopy
关于内核定时器,及DPC的使用,看来一些代码,这个估计是比较规范的用法了,很基础,希望对新手有帮助
注意,这里的定时器不太精确!
[cpp]view
plaincopy
#include<ntddk.h>
typedefstruct_DEVICE_EXTENSION{
LIST_ENTRYlist_head;
KSPIN_LOCKlist_lock;
PVOIDthread_pointer;
BOOLEANterminate_thread;
KEVENTrequest_event;
KTIMERmy_timer;
KDPCKiTimerExpireDpc;
}DEVICE_EXTENSION,*PDEVICE_EXTENSION;
#definedprintfif(DBG)DbgPrint
#definenprintfDbgPrint
#defineDEVICE_NAMEL"\\Device\\devhello"//DriverName
#defineLINK_NAMEL"\\DosDevices\\hello"//LinkName
//
//ThedevicedriverIOCTLs
//
#defineIOCTL_BASE0x800
#defineMY_CTL_CODE(i)\
CTL_CODE(FILE_DEVICE_UNKNOWN,IOCTL_BASE+i,METHOD_BUFFERED,FILE_ANY_ACCESS)
#defineIOCTL_HELLOMY_CTL_CODE(0)
/////////////////////////////////////////////////////////////////////
//函数声明
NTSTATUSDriverEntry(PDRIVER_OBJECTpDriverObj,PUNICODE_STRINGpRegistryString);
NTSTATUSDispatchCreate(PDEVICE_OBJECTpDevObj,PIRPpIrp);
NTSTATUSDispatchClose(PDEVICE_OBJECTpDevObj,PIRPpIrp);
VOIDDriverUnload(PDRIVER_OBJECTpDriverObj);
NTSTATUSDispatchIoctl(PDEVICE_OBJECTpDevObj,PIRPpIrp);
VOID
KiTimerExpirationFunction(
INstruct_KDPC*Dpc,
INPVOIDDeferredContext,
INPVOIDSystemArgument1,
INPVOIDSystemArgument2
);
NTSTATUSThreadFunc(INPVOIDContext);
/////////////////////////////////////////////////////////////////////
NTSTATUS
DriverEntry(
PDRIVER_OBJECTpDriverObj,
PUNICODE_STRINGpRegistryString
)
{
NTSTATUSstatus=STATUS_SUCCESS;
UNICODE_STRINGustrLinkName;
UNICODE_STRINGustrDevName;
PDEVICE_OBJECTdevice_object;
PDEVICE_EXTENSIONdevice_extension;
HANDLEthread_handle;
/*
在驱动中是以100纳秒为单位的
1000纳秒=1微秒
1000微秒=1毫秒
1000毫秒=1秒10*1000*1000
*/
LARGE_INTEGERduetime={0};
#definePOLLING_INTERVAL3000
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);
returnstatus;
}
RtlInitUnicodeString(&ustrLinkName,LINK_NAME);
status=IoCreateSymbolicLink(&ustrLinkName,&ustrDevName);
if(!NT_SUCCESS(status)){
dprintf("[hello]IoCreateSymbolicLink=0x%x\n",status);
IoDeleteDevice(device_object);
returnstatus;
}
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);
returnstatus;
}
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);
returnstatus;
}
ZwClose(thread_handle);
returnSTATUS_SUCCESS;
}
VOID
KiTimerExpirationFunction(
INstruct_KDPC*Dpc,
INPVOIDDeferredContext,
INPVOIDSystemArgument1,
INPVOIDSystemArgument2
)
{
PDEVICE_OBJECTpDevObj=(PDEVICE_OBJECT)DeferredContext;
PDEVICE_EXTENSIONdevice_extension=(PDEVICE_EXTENSION)pDevObj->DeviceExtension;
//kesetevent必需在较低级别用
//ASSERT(KeGetCurrentIrql()<=DISPATCH_LEVEL);
//dprintf("levelintimerfunctionis%x\n",KeGetCurrentIrql());
dprintf("hahadpcfunctionwork\n");
KeSetEvent(&device_extension->request_event,
(KPRIORITY)0,
FALSE);
};
NTSTATUSThreadFunc(INPVOIDContext)
{
PFILE_OBJECTConnectionFileObject,AddressFileObject;
HANDLEAddressHandle,ConnectionHandle;
NTSTATUSStatus;
IO_STATUS_BLOCKIoStatus;
KEVENTEvent;
PDEVICE_OBJECTdevice_object;
PDEVICE_EXTENSIONdevice_extension;
device_object=(PDEVICE_OBJECT)Context;
device_extension=(PDEVICE_EXTENSION)device_object->DeviceExtension;
KeSetPriorityThread(KeGetCurrentThread(),LOW_REALTIME_PRIORITY);
//****************************
//****************************
//开始工作此处用2重循环,你可以添加实际的代码
for(;;)
{
do
{
dprintf("threadworkok!!\n");
gotofailselabel;
}while(TRUE);
failselabel:
KeWaitForSingleObject(
&device_extension->request_event,
Executive,
KernelMode,
FALSE,
NULL
);//在这儿等
//KeClearEvent(&Event);//清除一下试试
//killvxk2007-01-3111:18
//严重提醒不要使用KeClearEvent(&Event);
//如果你还要用那个事件就不要用那个Clear,要其它手段~如果你不需要那个event了,
//那你应该在thread里判断下~
KeResetEvent(&device_extension->request_event);
if(device_extension->terminate_thread)
{
PsTerminateSystemThread(STATUS_SUCCESS);
}
}
dprintf("neverbehere!\n");
returnStatus;
}
VOID
DriverUnload(
PDRIVER_OBJECTpDriverObj
)
{
PDEVICE_EXTENSIONdevice_extension;
UNICODE_STRINGstrLink;
RtlInitUnicodeString(&strLink,LINK_NAME);
device_extension=(PDEVICE_EXTENSION)pDriverObj->DeviceObject->DeviceExtension;
//停止创建的线程
if(KeCancelTimer(&device_extension->my_timer)==FALSE)
{
//KeCancelTimer(&device_extension->my_timer);//取消定时器
dprintf("notimeractiveatterminate\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_OBJECTpDevObj,
PIRPpIrp
)
{
pIrp->IoStatus.Status=STATUS_SUCCESS;
pIrp->IoStatus.Information=0;
dprintf("[hello]IRP_MJ_CREATE\n");
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
returnSTATUS_SUCCESS;
}
NTSTATUS
DispatchClose(
PDEVICE_OBJECTpDevObj,
PIRPpIrp
)
{
pIrp->IoStatus.Status=STATUS_SUCCESS;
pIrp->IoStatus.Information=0;
dprintf("[hello]IRP_MJ_CLOSE\n");
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
returnSTATUS_SUCCESS;
}
NTSTATUS
DispatchIoctl(
PDEVICE_OBJECTpDevObj,
PIRPpIrp
)
{
NTSTATUSstatus=STATUS_INVALID_DEVICE_REQUEST;
PIO_STACK_LOCATIONpIrpStack;
ULONGuIoControlCode;
PVOIDpIoBuffer;
ULONGuInSize;
ULONGuOutSize;
pIrpStack=IoGetCurrentIrpStackLocation(pIrp);
uIoControlCode=pIrpStack->Parameters.DeviceIoControl.IoControlCode;
pIoBuffer=pIrp->AssociatedIrp.SystemBuffer;
uInSize=pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
uOutSize=pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch(uIoControlCode){
caseIOCTL_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);
returnstatus;
} |
|