DCP是一种使用更加灵活的定时器,可以对任意间隔时间进行定时。DPC定时器的内部使用了一个定时器对象KTIMER,当你设定了定时器之后,从设定开始起经过这个时间之后操作系统会将一个DPC定时器的例程插入到DPC的队列,操作系统读取DPC队列的时候定时器例程就能够被执行。这里的DPC定时器例程就相当于一个定时器的回调函数。

在使用需要一些相关的初始化操作

1,初始化Timer

VOID KeInitializeTimer(PKTIMER Timer);
//参数Timer是定时器的指针

2,初始化DPC对象

VOID KeInitializeDpc(PRKDPC Dpc,PKDEFERRED_ROUTINE DeferredRoutine,PVOID DeferredContext);
//Dpc是输入参数DPC的对象指针
//DeferredRoutine是一个与DPC关联的定时器例程函数,当定时器被触发的时候这个例程函数就会被执行调用
//DeferredContext是一个传入定时器例程的参数

3,当初始化完成之后使用函数KeSetTimer函数开启定时器,

BOOLEAN KeSetTimer( PKTIMER Timer,LARGE_INTEGER DueTime,PKDPC Dpc);
//Timer是定时器对象的指针.
//DueTimer这个参数是设定的时间间隔.
//Dpc表示传入定时器例程的参数.
//返回值:BOOL类型的,表示成功或者失败.

4,取消定时器使用内核函数KeCancelTimer,

BOOLEAN KeCancelTimer(PKTIMER Timer);

在调用KeSetTimer函数之后,经过DueTime的时间,操作系统会调用一次定时器的例程,其中如果DueTime是一个正整数,则会代表绝对时间,也就是相对于1601年1月1日到触发DPC定时器的那个时刻,如果DueTime是负数,那它表示的是间隔多长时间,DueTime的单位是100ns

示例代码:

用户层

#define IO_CONTROL_TRANSMIT_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN,0x8080,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IO_CONTROL_START_TIMER CTL_CODE(FILE_DEVICE_UNKNOWN,0x8081,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IO_CONTROL_STOP_TIMER CTL_CODE(FILE_DEVICE_UNKNOWN,0x8082,METHOD_IN_DIRECT,FILE_ANY_ACCESS) int main()
{
HANDLE hDevice = CreateFile(L"\\\\.\\MyDeviceSymbolLinkName01", GENERIC_READ | GENERIC_WRITE, , NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("failed to obtain file handle to device with win32 error code %d ...\n", GetLastError());
return ;
} DWORD dwOutput;
DWORD dwMircoSeconds = * * ;//100ns一个单位
//发送启动定时器命令
DeviceIoControl(hDevice, IO_CONTROL_START_TIMER, &dwMircoSeconds, sizeof(DWORD), NULL, , &dwOutput, NULL); Sleep();
//发送终止定时器命令
DeviceIoControl(hDevice, IO_CONTROL_STOP_TIMER, NULL, , NULL, , &dwOutput, NULL); CloseHandle(hDevice); return ;
}

驱动层:

//FirstDriver.h
#pragma once
#define IO_CONTROL_TRANSMIT_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN,0x8080,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IO_CONTROL_START_TIMER CTL_CODE(FILE_DEVICE_UNKNOWN,0x8081,METHOD_BUFFERED,FILE_ANY_ACCESS)
#define IO_CONTROL_STOP_TIMER CTL_CODE(FILE_DEVICE_UNKNOWN,0x8082,METHOD_IN_DIRECT,FILE_ANY_ACCESS)
typedef struct _DEVICE_EXTENSION
{
PDEVICE_OBJECT pDevObj;
UNICODE_STRING ustrDeviceName;
UNICODE_STRING ustrSymbolLinkName;
KDPC pollingDPC;
KTIMER pollingTimer;
LARGE_INTEGER pollingInterVal;
}DEVICE_EXTENSION, * PDEVICE_EXTENSION; NTSTATUS unload(PDRIVER_OBJECT driver); NTSTATUS DemoDeviceControlDispatch(PDEVICE_OBJECT pDeviceObject, PIRP pIrp); NTSTATUS DeviceCreate(PDEVICE_OBJECT pDeviceObject, PIRP pIrp);
NTSTATUS DeviceClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp); NTSTATUS DemoCreateDevice(PDRIVER_OBJECT pDriver, PCWSTR devName, PCWSTR devSymName);
//FirstDriver.c
#include <ntddk.h>
#include "FirstDriver.h" NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
NTSTATUS ntstatus = STATUS_SUCCESS;
driver->DriverUnload = unload;
driver->MajorFunction[IRP_MJ_CREATE] = DeviceCreate;//创建
driver->MajorFunction[IRP_MJ_CLOSE] = DeviceClose;//关闭
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DemoDeviceControlDispatch; ntstatus = DemoCreateDevice(driver, L"\\Device\\MyDevice01", L"\\??\\MyDeviceSymbolLinkName01");
if (!NT_SUCCESS(ntstatus))
{
DbgPrint("IoCreateDevice Failed");
return ntstatus;
} DbgPrint("%ws", reg_path->Buffer);
DbgPrint("driver load success...");
return STATUS_SUCCESS;
} VOID PollingTimerDPC(PKDPC pDpc, PVOID pContext, PVOID SysArg1, PVOID SysArg2)
{
PDEVICE_OBJECT pDevObj = (PDEVICE_OBJECT)pContext;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)pDevObj->DeviceExtension; KeSetTimer(&pdx->pollingTimer, pdx->pollingInterVal, &pdx->pollingDPC);
KdPrint(("PollingTimerDpc\n")); //检验是运行在任意线程上下文
PEPROCESS pEProcess = IoGetCurrentProcess(); PTSTR ProcessName = (PTSTR)((LONGLONG)pEProcess + 0x174); DbgPrint("多余参数 %d , %d , %d", pDpc->Number, SysArg1, SysArg2);
DbgPrint("%s\n", ProcessName);
} NTSTATUS DemoDeviceControlDispatch(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
NTSTATUS ntstatus = STATUS_SUCCESS;
DbgPrint("enter DemoDeviceControlDispatch ...\n"); PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
//ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
ULONG ctlCode = stack->Parameters.DeviceIoControl.IoControlCode;
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension; ULONG info = ;
switch (ctlCode)
{
case IO_CONTROL_START_TIMER:
{ KdPrint(("IOCTL_START_TIMER!\n")); //从用户模式传进来的超时
ULONG ulMircoSeconds = *(PULONG)pIrp->AssociatedIrp.SystemBuffer; pDevExt->pollingInterVal = RtlConvertLongToLargeInteger(ulMircoSeconds * -); KeSetTimer(&pDevExt->pollingTimer, pDevExt->pollingInterVal, &pDevExt->pollingDPC); break;
}
case IO_CONTROL_STOP_TIMER:
{
KdPrint(("IOCTL_STOP_TIMER!\n")); KeCancelTimer(&pDevExt->pollingTimer); break;
}
default:
ntstatus = STATUS_INVALID_VARIANT;
break;
}
pIrp->IoStatus.Status = ntstatus;
pIrp->IoStatus.Information = info;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
DbgPrint("leave the demo device control dispatch ...");
DbgPrint("device io control test success...%d", pDeviceObject->ActiveThreadCount);
return ntstatus;
} NTSTATUS DeviceCreate(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
//业务代码区 //设置返回状态
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = ;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
DbgPrint("create device success...%d", pDeviceObject->ActiveThreadCount);
return STATUS_SUCCESS;
} NTSTATUS DeviceClose(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
//业务代码区 //设置返回状态
pIrp->IoStatus.Status = STATUS_SUCCESS;//getLastError()得到的值
pIrp->IoStatus.Information = ; //返回给3环多少数据,没有填0
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
DbgPrint("close device success...%d", pDeviceObject->ActiveThreadCount);
return STATUS_SUCCESS;
} NTSTATUS DemoCreateDevice(PDRIVER_OBJECT pDriver, PCWSTR devName, PCWSTR devSymName)
{
PDEVICE_OBJECT pDevice;
PDEVICE_EXTENSION pDevExt; UNICODE_STRING DeviceName;
UNICODE_STRING SymbolLinkName; RtlInitUnicodeString(&DeviceName, devName);
RtlInitUnicodeString(&SymbolLinkName, devSymName); NTSTATUS ntstatus = STATUS_SUCCESS;
ntstatus = IoCreateDevice(pDriver, sizeof(DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &pDevice);
if (!NT_SUCCESS(ntstatus))
{
DbgPrint("IoCreateDevice Failed");
return ntstatus;
} ntstatus = IoCreateSymbolicLink(&SymbolLinkName, &DeviceName);
if (!NT_SUCCESS(ntstatus))
{
DbgPrint("IoCreateSymbolicLink Failed");
IoDeleteDevice(pDevice);
return ntstatus;
} pDevice->Flags |= DO_BUFFERED_IO; pDevExt = (PDEVICE_EXTENSION)pDevice->DeviceExtension;
pDevExt->pDevObj = pDevice;
pDevExt->ustrDeviceName = DeviceName;
pDevExt->ustrSymbolLinkName = SymbolLinkName; KeInitializeTimer(&pDevExt->pollingTimer);
KeInitializeDpc(&pDevExt->pollingDPC, PollingTimerDPC, (PVOID)pDevice);
return ntstatus;
} NTSTATUS unload(PDRIVER_OBJECT driver)
{
PDEVICE_OBJECT pDev;
DbgPrint("driver :%ws unload", driver->DriverName.Buffer);
pDev = driver->DeviceObject;
while (pDev != NULL)
{
PDEVICE_EXTENSION pDevExt = { };
pDevExt = (PDEVICE_EXTENSION)pDev->DeviceExtension; //删除符号链接
UNICODE_STRING pLinkName = pDevExt->ustrSymbolLinkName;
DbgPrint("this is the divice name : %ws", pLinkName.Buffer);
IoDeleteSymbolicLink(&pLinkName);
pDev = pDev->NextDevice;
IoDeleteDevice(pDevExt->pDevObj);
}
DbgPrint("driver unload success...");
return STATUS_SUCCESS;
}

Windows驱动开发-DPC定时器的更多相关文章

  1. Windows驱动开发(中间层)

    Windows驱动开发 一.前言 依据<Windows内核安全与驱动开发>及MSDN等网络质料进行学习开发. 二.初步环境 1.下载安装WDK7.1.0(WinDDK\7600.16385 ...

  2. [Windows驱动开发](一)序言

    笔者学习驱动编程是从两本书入门的.它们分别是<寒江独钓——内核安全编程>和<Windows驱动开发技术详解>.两本书分别从不同的角度介绍了驱动程序的制作方法. 在我理解,驱动程 ...

  3. windows驱动开发推荐书籍

    [作者] 猪头三 个人网站 :http://www.x86asm.com/ [序言] 很多人都对驱动开发有兴趣,但往往找不到正确的学习方式.当然这跟驱动开发的本土化资料少有关系.大多学的驱动开发资料都 ...

  4. Windows 驱动开发 - 5

    上篇<Windows 驱动开发 - 4>我们已经完毕了硬件准备. 可是我们还没有详细的数据操作,比如接收读写操作. 在WDF中进行此类操作前须要进行设备的IO控制,已保持数据的完整性. 我 ...

  5. windows 驱动开发入门——驱动中的数据结构

    最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...

  6. Windows驱动——读书笔记《Windows驱动开发技术详解》

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  请通过右侧公告中的“联系邮 ...

  7. Windows 驱动开发 - 7

    在<Windows 驱动开发 - 5>我们所说的读写操作在本篇实现. 在WDF中实现此功能主要为:EvtIoRead和EvtIoWrite. 首先,在EvtDeviceAdd设置以上两个回 ...

  8. Windows 驱动开发 - 8

    最后的一点开发工作:跟踪驱动. 一.驱动跟踪 1. 包括TMH头文件 #include "step5.tmh" 2. 初始化跟踪 在DriverEntry中初始化. WPP_INI ...

  9. Windows驱动开发-IRP的完成例程

    <Windows驱动开发技术详解 >331页, 在将IRP发送给底层驱动或其他驱动之前,可以对IRP设置一个完成例程,一旦底层驱动将IRP完成后,IRP完成例程立刻被处罚,通过设置完成例程 ...

随机推荐

  1. 前端之HTML基础篇

    HTML基础篇 目录                                                                               本章内容: 简介 1. ...

  2. kali Linux 2020.1最新安装教程,亲身尝试,绝对能帮你安装好!不是root、没有桌面、中文乱码、下载太慢、ssh链接等问题!

    既然已经开始研究kali Linux,小编就认为在下已经有了一定的基础.当然小编也是个小白用户.本人用的是Vmware虚拟机,这里只说一点,内存我选择的是4g因为这个包含桌面,所以稍微大一点.Linx ...

  3. 09-Docker-Volumes数据管理

    目录 09-Docker-Volumes数据管理 参考 数据卷类型 数据卷操作 bind数据卷 volume数据卷 tmpfs数据卷 09-Docker-Volumes数据管理 Docker Vers ...

  4. H5拖动事件复习

    定义和用法 ondrag 事件在元素或者选取的文本被拖动时触发. 拖放是 HTML5 中非常常见的功能. 更多信息可以查看我们 HTML 教程中的 HTML5 拖放. 注意: 为了让元素可拖动,需要使 ...

  5. strtok() and strtod()

    1.strtok(参数1,参数2)按指定的分割符将字符串分割开来 参数1:表示要被分割的字符串的地址: 参数2:表示指定的分割符的地址: 例如:按空格分割“Hello World” buffer[] ...

  6. git按需过滤提交文件的一个细节

    问题场景 用git管理代码时,作为git小白的我总会遇到一些无法理解的问题,在请教了一些高手后终于解开了疑惑,参考以下场景: 1.比如我们已在电脑1上完成用vs编辑项目.添加.提交到服务器的完整流程, ...

  7. VLAN配置Trunk接口

    实验二:配置Trunk接口. 实验原理: 实验内容: 本实验模拟某公司网络场景.公司规模较大,员工200余名,内部网络是-一个大的局域网.公司放置了多台接入交换机(如S1和S2)负责员工的网络接入.接 ...

  8. Apache Thrift Learning Notes

    简介 Apache Thrift软件框架(用于可扩展的跨语言服务开发)将软件堆栈与代码生成引擎结合在一起,以构建可在C ++,Java,Python,PHP,Ruby,Erlang,Perl,Hask ...

  9. 具体的client-server通信模型以及最为常用的通信模式

    实现虚拟网络服务的主要技术,指出IP负载均衡技术是在负载调度器的实现技术中效率最高的. 在已有的IP负载均衡技术中: 1)有通过网络地址转换(Network Address Translation)将 ...

  10. 批量离线安装jar 包到maven本地仓库

    //installer.bat@echo offset localdir=%~dp0call mvn install:install-file -DgroupId=org.zhixun -Dartif ...