定时器

在驱动程序中,一般有两种方法使用定时器,一种方法是使用I/O定时器例程,另一
种方法是使用DPC例程。
每隔1S系统会调用一次I/0定时器例程,可以在定时器例程里面设置一个计数,每次定时器例程运行都将该计数-1.到0就调用自己的处理函数。这样就实现了任意时间间隔的定时。
初始化I/O定时器

NTSTATUS IoInitializeTimer(
  PDEVICE_OBJECT         DeviceObject,	//I/O定时器关联的设备对象指针
  PIO_TIMER_ROUTINE      TimerRoutine,	///I/O定时器关联的定时器例程
  __drv_aliasesMem PVOID Context		//传入定时器例程的参数
);

开启I/O定时器
IoStartTimer
停止I/O定时器
IoStopTimer

示例代码

#include<ntddk.h>
#include<ntstatus.h>
#include "Driver.h"

#define DEVICE_NAME L"\\Device\\MyDevice"
#define SYMBOLICLINE_NAME L"\\??\\MyTestDriver"  //ring3用CreateFile打开设备时,用"\\\\.\\MyTestDriver"//相当于起的别名
#define TIMEOUT 3
#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)

PVOID pDeviceExtension = 0;

//实现卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	PDEVICE_OBJECT	pNextObj;
	KdPrint(("Enter DriverUnload\n"));
	pNextObj = pDriverObject->DeviceObject;
	__asm{ int 3}
	while (pNextObj != NULL)
	{
		PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
			pNextObj->DeviceExtension;

		//删除符号链接
		UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
		IoDeleteSymbolicLink(&pLinkName);

		pNextObj = pNextObj->NextDevice;
		IoDeleteDevice(pDevExt->pDevice);
		DbgPrint("删除设备\n");
	}
	
}

NTSTATUS IrpDefaultProc(PDEVICE_OBJECT pDeviceObject/*设备信息*/, PIRP pIrp/*参数信息*/)
{

	pIrp->IoStatus.Status = STATUS_SUCCESS;//getlasterror()得到的就是这个值
	pIrp->IoStatus.Information = 0;//返回给3环多少数据,没有填0
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

IO_TIMER_ROUTINE IoTimerRoutine;


void IoTimerRoutine(
	PDEVICE_OBJECT pDeviceObject,
	PVOID Context
	)
{
	PDEVICE_EXTENSION pDevExt = pDeviceObject->DeviceExtension;

	//将计数器-1
	InterlockedDecrement(&pDevExt->TimeOut);
	//如果计数器减少到0 重新赋值TIME_OUT 整个过程是互锁运算
	ULONG prevCount = InterlockedCompareExchange(&pDevExt->TimeOut, TIMEOUT, 0);
	PEPROCESS pEprocess = IoGetCurrentProcess();
	if (strcmp((PUCHAR)pEprocess + 0x174,"Idle"))
	{
		
		DbgPrint("当前进程是:%s\n", (PUCHAR)pEprocess + 0x174);
	}

	if (!prevCount)
	{
		//自己的定时任务
	}

}


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
{

	NTSTATUS status = 0;
	ULONG uIndex = 0;
	PDEVICE_OBJECT pDeviceObj = NULL;
	UNICODE_STRING DeviceName;
	UNICODE_STRING SymbolicLinkName;

	//Irp默认处理
	pDriver->MajorFunction[IRP_MJ_CREATE] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_WRITE] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_READ] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_CLEANUP] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_SET_INFORMATION] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_SHUTDOWN] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IrpDefaultProc;

	//设置派遣函数和卸载函数	
	pDriver->DriverUnload = DriverUnload;


	//创建设备名称
	RtlInitUnicodeString(&DeviceName, DEVICE_NAME);

	//创建设备  让三环的API能够找到,才能实现通信
	status = IoCreateDevice(pDriver,
		sizeof(DEVICE_EXTENSION),	//扩展设备大小 
		&DeviceName,
		FILE_DEVICE_UNKNOWN, 
		0,
		TRUE,
		&pDeviceObj);
	if (status != STATUS_SUCCESS)
	{
		DbgPrint("创建设备失败! status=%x\r\n", status);
		return status;
	}
	
	//设置交互数据方式
	pDeviceObj->Flags |= DO_BUFFERED_IO;

	//创建符号链接名称,就是给该设备在三环起个能用的别名
	RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINE_NAME);

	//创建符号链接
	status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("创建符号链接失败!\r\n");
		IoDeleteDevice(pDeviceObj);
		return status;
	}

	//初始化定时器
	PDEVICE_EXTENSION pDevExt = pDeviceObj->DeviceExtension;
	pDevExt->pDevice = pDeviceObj;
	pDevExt->ustrDeviceName = DeviceName;
	pDevExt->ustrSymLinkName = SymbolicLinkName;

	//设置计数为3
	pDevExt->TimeOut = TIMEOUT;
	IoInitializeTimer(pDeviceObj,IoTimerRoutine,NULL);

	//开启定时器  关闭使用IoStopTimer
	IoStartTimer(pDeviceObj);
	return STATUS_SUCCESS;

}


DPC定时器

在驱动程序中第二种使用定时器的方法是使用DPC定时器,这种定时器更加灵活,
可以对任意间隔时间进行定时。DPC定时器内部使用定时器对象KTIMER,当对定时器设
定一个时间间隔后,每隔这段时间操作系统就会将一个DPC例程插入DPC队列。当操作
系统读取DPC队列时,对应的DPC例程会被执行。DPC定时器例程相当于定时器的回调
函数。

在使用DPC定时器前,需要初始化DPC对象和定时器对象
初始化DPC对象
初始化定时器对象使用KeInitializeTimer

void KeInitializeDpc(
  __drv_aliasesMem PRKDPC Dpc,		DPC对象指针
  PKDEFERRED_ROUTINE      DeferredRoutine,	//与DPC关联的DPC例程
  __drv_aliasesMem PVOID  DeferredContext	//传入DPC例程的参数
);

开启定时器

BOOLEAN KeSetTimer(
  PKTIMER       Timer,	//定时器对象指针
  LARGE_INTEGER DueTime,	//设定事件间隔	单位是100ns
  PKDPC         Dpc	//传入DPC例程的参数
);

返回值:设定定时器成功返回TRUE

取消定时器

BOOLEAN KeCancelTimer(
  PKTIMER   Timer,	//定时器对象指针

DPC定时器使用代码:

typedef struct _DEVICE_EXTENSION {
	PDEVICE_OBJECT pDevice;
	UNICODE_STRING ustrDeviceName;	//设备名称
	UNICODE_STRING ustrSymLinkName;	//符号链接名
	KDPC dpc;
	KTIMER timer;
	LARGE_INTEGER dueTime;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

#include<ntddk.h>
#include<ntstatus.h>
#include "Driver.h"

#define DEVICE_NAME L"\\Device\\MyDevice"
#define SYMBOLICLINE_NAME L"\\??\\MyTestDriver"  //ring3用CreateFile打开设备时,用"\\\\.\\MyTestDriver"//相当于起的别名
#define TIMEOUT 3
#define OPER1 CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define OPER2 CTL_CODE(FILE_DEVICE_UNKNOWN,0x900,METHOD_BUFFERED,FILE_ANY_ACCESS)

PVOID pDeviceExtension = 0;

//实现卸载函数
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	PDEVICE_OBJECT	pNextObj;
	KdPrint(("Enter DriverUnload\n"));
	pNextObj = pDriverObject->DeviceObject;
	while (pNextObj != NULL)
	{
		PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
			pNextObj->DeviceExtension;

		//删除符号链接
		UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
		IoDeleteSymbolicLink(&pLinkName);

		pNextObj = pNextObj->NextDevice;
		IoDeleteDevice(pDevExt->pDevice);
		DbgPrint("删除设备\n");
	}
	
}

NTSTATUS IrpDefaultProc(PDEVICE_OBJECT pDeviceObject/*设备信息*/, PIRP pIrp/*参数信息*/)
{

	pIrp->IoStatus.Status = STATUS_SUCCESS;//getlasterror()得到的就是这个值
	pIrp->IoStatus.Information = 0;//返回给3环多少数据,没有填0
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

IO_TIMER_ROUTINE IoTimerRoutine;

#pragma LOCKEDCODE
void DpcRoutine(
	PKDPC  pDpc,
	PVOID Context,
	PVOID Arg1,
	PVOID Arg2
	)
{

	PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)Context;
	PEPROCESS pEprocess = IoGetCurrentProcess();
	DbgPrint("当前进程是:%s\n", (PUCHAR)pEprocess + 0x174);
	//调用1次KeSetTimer只会运行一次DPC Routine 
	KeSetTimer(&pDevExt->timer, pDevExt->dueTime, &pDevExt->dpc);
}


NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING reg_path)
{

	NTSTATUS status = 0;
	ULONG uIndex = 0;
	PDEVICE_OBJECT pDeviceObj = NULL;
	UNICODE_STRING DeviceName;
	UNICODE_STRING SymbolicLinkName;

	//Irp默认处理
	pDriver->MajorFunction[IRP_MJ_CREATE] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_CLOSE] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_WRITE] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_READ] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_CLEANUP] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_SET_INFORMATION] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_SHUTDOWN] = IrpDefaultProc;
	pDriver->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = IrpDefaultProc;

	//设置派遣函数和卸载函数	
	pDriver->DriverUnload = DriverUnload;


	//创建设备名称
	RtlInitUnicodeString(&DeviceName, DEVICE_NAME);

	//创建设备  让三环的API能够找到,才能实现通信
	status = IoCreateDevice(pDriver,
		sizeof(DEVICE_EXTENSION),	//扩展设备大小 
		&DeviceName,
		FILE_DEVICE_UNKNOWN, 
		0,
		TRUE,
		&pDeviceObj);
	if (status != STATUS_SUCCESS)
	{
		DbgPrint("创建设备失败! status=%x\r\n", status);
		return status;
	}
	
	//设置交互数据方式
	pDeviceObj->Flags |= DO_BUFFERED_IO;

	//创建符号链接名称,就是给该设备在三环起个能用的别名
	RtlInitUnicodeString(&SymbolicLinkName, SYMBOLICLINE_NAME);

	//创建符号链接
	status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName);
	if (!NT_SUCCESS(status))
	{
		DbgPrint("创建符号链接失败!\r\n");
		IoDeleteDevice(pDeviceObj);
		return status;
	}
	PDEVICE_EXTENSION pDevExt = pDeviceObj->DeviceExtension;
	pDevExt->pDevice = pDeviceObj;
	pDevExt->ustrDeviceName = DeviceName;
	pDevExt->ustrSymLinkName = SymbolicLinkName;
	pDevExt->dueTime.QuadPart = -1 * 1000 * 1000;
	
	//初始化定时器对象
	KeInitializeTimer(&pDevExt->timer);
	//初始化DPC对象
	KeInitializeDpc(&pDevExt->dpc, DpcRoutine, pDevExt);

	KeSetTimer(&pDevExt->timer, pDevExt->dueTime, &pDevExt->dpc);
	return STATUS_SUCCESS;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值