看流星社区

 找回密码
 注册账号
查看: 1870|回复: 0

关于内核定时器,DPC,线程的使用

[复制链接]

该用户从未签到

发表于 2017-6-1 14:49:59 | 显示全部楼层 |阅读模式
[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(&amp;ustrDevName,DEVICE_NAME);
status=IoCreateDevice(pDriverObj,
sizeof(DEVICE_EXTENSION),
&amp;ustrDevName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&amp;device_object);
if(!NT_SUCCESS(status)){
dprintf("[hello]IoCreateDevice=0x%x\n",status);
returnstatus;
}
RtlInitUnicodeString(&amp;ustrLinkName,LINK_NAME);
status=IoCreateSymbolicLink(&amp;ustrLinkName,&amp;ustrDevName);

if(!NT_SUCCESS(status)){
dprintf("[hello]IoCreateSymbolicLink=0x%x\n",status);
IoDeleteDevice(device_object);
returnstatus;
}
device_extension=(PDEVICE_EXTENSION)device_object->DeviceExtension;
InitializeListHead(&amp;device_extension->list_head);
KeInitializeSpinLock(&amp;device_extension->list_lock);

KeInitializeEvent(&amp;device_extension->request_event,
NotificationEvent,
FALSE);
//KeInitializeTimer(&amp;my_timer);//这是个旧的函数
KeInitializeTimerEx(&amp;device_extension->my_timer,NotificationTimer);
//初始化定时器过期的DPC对象
KeInitializeDpc(&amp;device_extension->KiTimerExpireDpc,
(PKDEFERRED_ROUTINE)KiTimerExpirationFunction,(PVOID)device_object);
//KeSetTimer(&amp;my_timer,timeout,&amp;KiTimerExpireDpc);仅仅只能设置一次
//KeSetTimerEx(&amp;my_timer,timeout,period,&amp;KiTimerExpireDpc);这个可以循环设置
KeSetTimerEx(&amp;device_extension->my_timer,duetime,POLLING_INTERVAL,&amp;device_extension->KiTimerExpireDpc);
//KeSetTimerEx语句启动周期定时器。由于duetime参数是0,
//所以定时器立即进入信号态。
//然后每隔POLLING_INTERVAL=3秒触发一次。
device_extension->terminate_thread=FALSE;

status=PsCreateSystemThread(
&amp;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,
&amp;device_extension->thread_pointer,
NULL
);

if(!NT_SUCCESS(status))
{
ZwClose(thread_handle);
device_extension->terminate_thread=TRUE;//如果出错就关闭创建的线程

KeSetEvent(
&amp;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(&amp;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(
&amp;device_extension->request_event,
Executive,
KernelMode,
FALSE,
NULL
);//在这儿等
//KeClearEvent(&amp;Event);//清除一下试试
//killvxk2007-01-3111:18
//严重提醒不要使用KeClearEvent(&amp;Event);
//如果你还要用那个事件就不要用那个Clear,要其它手段~如果你不需要那个event了,
//那你应该在thread里判断下~
KeResetEvent(&amp;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(&amp;strLink,LINK_NAME);
device_extension=(PDEVICE_EXTENSION)pDriverObj->DeviceObject->DeviceExtension;
//停止创建的线程
if(KeCancelTimer(&amp;device_extension->my_timer)==FALSE)
{
//KeCancelTimer(&amp;device_extension->my_timer);//取消定时器
dprintf("notimeractiveatterminate\n");
}
device_extension->terminate_thread=TRUE;//停止线程
KeSetEvent(
&amp;device_extension->request_event,
(KPRIORITY)0,
FALSE
);
KeWaitForSingleObject(
device_extension->thread_pointer,//等待线程对象结束,注意哦,是对象
Executive,
KernelMode,
FALSE,
NULL
);
ObDereferenceObject(device_extension->thread_pointer);
IoDeleteSymbolicLink(&amp;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;
}
点击按钮快速添加回复内容: 支持 高兴 激动 给力 加油 苦寻 生气 回帖 路过 感恩
您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

小黑屋|手机版|Archiver|看流星社区 |网站地图

GMT+8, 2024-3-19 18:00

Powered by Kanliuxing X3.4

© 2010-2019 kanliuxing.com

快速回复 返回顶部 返回列表