Windows编程—Windows驱动中定时器的使用
文章目录
- Windows编程—Windows驱动中定时器的使用
- 前言
- 代码
- 简单版
- 升级版
- 程序效果
Windows编程—Windows驱动中定时器的使用
前言
定时器操作是应用编程中非常常见的操作,同样的在Windows内核驱动编程中也有对应的API。在Windows应用编程中使用的是SetTimer进行定时器编程,在Windows驱动开发中也有对应的API。主要用的下面3个API。
// 1.初始化定时器
VOID KeInitializeTimer(// 指向要初始化的定时器,调用者分配空间IN PKTIMER Timer);// 2.初始化dpc结构体对应,可以指定定时器回调函数
VOID KeInitializeDpc(// 指向KDPC结构体指针,调用者必须自己分配持久的内存空间IN PRKDPC Dpc,// 定时器回调函数,函数原型 CustomDpc IN PKDEFERRED_ROUTINE DeferredRoutine,// 回调函数上下文参数,会在调用定时器回调函数时作为参数2传入IN PVOID DeferredContext);// 3.启动定时器
BOOLEAN KeSetTimer(// 已经初始化好的定时器IN PKTIMER Timer,// 延时执行回调函数的相对时间 或者 绝对时间,相对时间使用负数(单位为100ns),正数会被视为绝对时间 该时间依赖操作系统时间IN LARGE_INTEGER DueTime,// 指向dpc结构体的指针,主要用于和定时器回调函数关联的IN PKDPC Dpc OPTIONAL);// CustomDpc原型
KDEFERRED_ROUTINE CustomDpc;
VOIDCustomDpc(__in struct _KDPC *Dpc,__in_opt PVOID DeferredContext,__in_opt PVOID SystemArgument1,__in_opt PVOID SystemArgument2){...}
代码
简单版
按照参数要求 可以写个简单版的定时器,需要分配空间的 都用全局变量 提前分配好。代码中有详细注释。
MyTimer.c
#include <ntddk.h>
#include <Ntstrsafe.h>
#pragma ("Ntstrsafe.lib",lib)VOID DriverUnload(PDRIVER_OBJECT driver)
{DbgPrint("02-DriverUnload enter\r\n");
}PWCHAR MyCurTimeStr()
{LARGE_INTEGER snow,now;TIME_FIELDS now_fields;static WCHAR time_str[32] = { 0 };// 获得标准时间KeQuerySystemTime(&snow);// 转换为当地时间ExSystemTimeToLocalTime(&snow,&now);// 转换为人类可以理解的时间要素RtlTimeToTimeFields(&now,&now_fields);// 打印到字符串中RtlStringCchPrintfW(time_str,32*2,L"%4d-%d-%2d %2d:%2d:%d",now_fields.Year,now_fields.Month,now_fields.Day,now_fields.Hour,now_fields.Minute,now_fields.Second);return time_str;
}// 这些都可以封装在一个构体中
KTIMER my_timer;
KDPC my_dpc;
unsigned int timer_count = 5; // 定时器回调函数执行次数
unsigned int timer_interval = 5000 ; // 定时器执行间隔时间msVOID MyCustomDpc(IN struct _KDPC *Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2
)
{PKTIMER pTimer = (PKTIMER)DeferredContext;LARGE_INTEGER time;static int i = 1;time.QuadPart = -10000; time.QuadPart *= timer_interval;if( --timer_count > 0){// 继续启动定时器KeSetTimer(pTimer,time,&my_dpc);}DbgPrint("%ws MyCustomDpc enter %d \r\n",MyCurTimeStr(),i++);
}// DriverEntry,入口函数。
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{// 设置断点
#if DBG// _asm int 3
#endif// 注意所有的变量要声明在函数的最开头LARGE_INTEGER time;DbgPrint("02-DriverEntry enter\r\n");// 1.初始化定时器KeInitializeTimer(&my_timer);// 2.初始化Dpc,也就是初始化 延时执行的回调函数结构// 将my_timer作为定时回调MyCustomDpc的context,方便执行完后继续下一次定时。// 所以这可以继续封装,可以将需要的封装成一个结构体往里面传,然后在回调函数中可以取到KeInitializeDpc(&my_dpc,MyCustomDpc,&my_timer); // 延时单位为100ns,1ms = 1000us = 10000 00ns // 此时延时1ms,且必须为负数,负数才认为是相对时间否则认为是绝对时间time.QuadPart = -10000; time.QuadPart *= timer_interval;// 3.启动定时器KeSetTimer(&my_timer,time,&my_dpc);driver->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}
升级版
自己简单封装一下,代码中有详细注释。MyTimer.c
#include <ntddk.h>
#include <Ntstrsafe.h>
#pragma ("Ntstrsafe.lib",lib)VOID DriverUnload(PDRIVER_OBJECT driver)
{DbgPrint("03—DriverUnload enter\r\n");
}PWCHAR MyCurTimeStr()
{LARGE_INTEGER snow,now;TIME_FIELDS now_fields;static WCHAR time_str[32] = { 0 };// 获得标准时间KeQuerySystemTime(&snow);// 转换为当地时间ExSystemTimeToLocalTime(&snow,&now);// 转换为人类可以理解的时间要素RtlTimeToTimeFields(&now,&now_fields);// 打印到字符串中RtlStringCchPrintfW(time_str,32*2,L"%4d-%d-%2d %2d:%2d:%d",now_fields.Year,now_fields.Month,now_fields.Day,now_fields.Hour,now_fields.Minute,now_fields.Second);return time_str;
}// 定义自己封装的定时器timer
typedef struct MyTimer
{KTIMER m_timer; // timer结构 KDPC m_dpc; // dpc结构PKDEFERRED_ROUTINE m_func; // 定时触发的回调函数unsigned int m_count; // 执行次数unsigned int m_interval; // 间隔时间,单位ms
}MyTimer,*PMyTimer;// 1.定时器相关内容初始化
VOID MyTimerInit(PMyTimer timer, // 初始化的定时结构体PKDEFERRED_ROUTINE func,// 定时器回调函数unsigned int count, // 定时器执行次数unsigned int interval // 执行间隔,单位ms)
{timer->m_func = func;timer->m_count = count;timer->m_interval = interval;KeInitializeTimer(&timer->m_timer);KeInitializeDpc(&timer->m_dpc,timer->m_func,timer);
}// 2.启动定时器
VOID MyTimerSet(PMyTimer timer)
{LARGE_INTEGER time;time.QuadPart = -10000;time.QuadPart *= timer->m_interval;KeSetTimer(&timer->m_timer,time,&timer->m_dpc);
}// 定时器回调函数
VOID MyCustomDpc(IN struct _KDPC *Dpc,IN PVOID DeferredContext,IN PVOID SystemArgument1,IN PVOID SystemArgument2
)
{PMyTimer pTimer = (PMyTimer)DeferredContext;static int i = 1;if( --pTimer->m_count > 0){// 继续启动定时器MyTimerSet(pTimer);}DbgPrint("%ws MyCustomDpc enter %d \r\n",MyCurTimeStr(),i++);
}MyTimer g_timer;// DriverEntry,入口函数。
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{// 设置断点
#if DBG// _asm int 3
#endif// 1.定时器相关初始化MyTimerInit(&g_timer,MyCustomDpc,5,5000);// 2.启动定时器MyTimerSet(&g_timer);DbgPrint("03-DriverEntry enter\r\n");driver->DriverUnload = DriverUnload;return STATUS_SUCCESS;
}
程序效果
2个示例程序运行效果。
Windows编程—Windows驱动中定时器的使用相关推荐
- Windows编程—Windows驱动开发环境搭建
文章目录 前言 步骤 步骤一 步骤二 步骤三 连接测试 步骤四 步骤五 总结 前言 作为一个编写Windows程序的开发人员,对Windows驱动开发 并非必需要掌握,但是掌握 Windows驱动开发 ...
- Windows编程 Windows程序的生与死(下)
再谈程序之"死" 记得在第二回中我对程序的"死"只是一句话带过,因为我还没有铺垫好,好了现在我们可以详细的分析一下这个过程了. 这还要从while消息循环说起, ...
- 驱动中定时器,taskle,工作队列编程
一.定时器 1.内核时间相关转换函数 unsigned long usecs_to_jiffies(const unsigned int u) 功能: 把微秒转换成时钟节拍 参数: u 时间微秒 返回 ...
- C/C++:Windows编程—Windows RPC 传递自定义数据类型、自定义数据类型数组、指针数组
前言 该篇博文不是讲Windows rpc入门的.是笔者在实际使用Windows RPC时 所遇到的问题,以及解决方法. 笔者有这样的需求,需要从RPC Server获取大量数据,而且该数据是动态分配 ...
- Windows编程(2)
文章目录 windows有关的重要概念 句柄 窗口 Windows的消息机制 消息结构体 宽字符与Unicode 宽字符串的长度 ASCII 和 Unicode 兼容性问题 Windows数据类型 w ...
- Linux 设备驱动中的 I/O模型(一)—— 阻塞和非阻塞I/O
在前面学习网络编程时,曾经学过I/O模型 Linux 系统应用编程--网络编程(I/O模型),下面学习一下I/O模型在设备驱动中的应用. 回顾一下在Unix/Linux下共有五种I/O模型,分别是: ...
- Linux 设备驱动中的阻塞与非阻塞 I/O
阻塞操作是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作.被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足.而非阻塞操作的进程在不能进行设备操作时 ...
- windows 驱动开发入门——驱动中的数据结构
最近在学习驱动编程方面的内容,在这将自己的一些心得分享出来,供大家参考,与大家共同进步,本人学习驱动主要是通过两本书--<独钓寒江 windows安全编程> 和 <windows驱动 ...
- Windows内核驱动中操作文件
一. 在驱动中使用文件 在Windows执行体中,通过文件对象来代表文件,该文件对象是一种由对象管理器管理的执行体对象.例如:目录也是由文件对象代表的. 内核组件通过对象名来引用文件,即在文件的全路径 ...
最新文章
- Zabbix安装配置(CentOS7.3)
- 动手动脑——登录界面
- 【转】c++重载、覆盖、隐藏——理不清的区别
- 跨平台使用exp/imp进行数据库转移时出现丢失对象的原因
- 子页面赋值给父页面:window.opener.document.getElementById
- spring-chapter02-IoC Container
- python中函数的参数传递
- 固态硬盘系统经常假死_Win7固态硬盘假死卡顿解决方法
- 四川大学计算机学院2020推免公示,2020年四川大学计算机(软件)学院夏令营接收推免生条件...
- 单细胞测序流程(二)数据整理
- linux 内网gcc版本安装,linux下手动安装/升级GCC到较高版本
- GPRS模块(sim900a)联网(PC)测试失败篇
- 【Android -- 写作工具】Markdown 图片
- 2019牛客暑期多校训练营(第一场)E : ABBA(dp)
- Simpsons’ Hidden Talents
- Python+Qt抽奖点名工具源码窗体程序
- 深度学习:自编码进行模式分类
- 汇编语言 -- 计时器/倒计时
- 如何更改MFC的项目名称
- 2018年7月面试记录
热门文章
- Hemberg-lab单细胞转录组数据分析(一)
- C4D插件:Springy for Mac 动​​画对象添加重叠动作插件
- 《数学与生活》的3本书籍
- laravel windos 无法生成 appkey 的问题解决方法
- php模拟远程提交get 、post 实例函数
- python字符数组输出_python字符串格式化输出
- git fetch 与 git pull
- 稳压电源的设计与制作_电子爱好设计的直流可调压电源电路,太完美了,有图,亲测可用...
- C++工作笔记-多继承下的一个大坑
- docker 提交自定义镜像