文章目录

  • 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驱动中定时器的使用相关推荐

  1. Windows编程—Windows驱动开发环境搭建

    文章目录 前言 步骤 步骤一 步骤二 步骤三 连接测试 步骤四 步骤五 总结 前言 作为一个编写Windows程序的开发人员,对Windows驱动开发 并非必需要掌握,但是掌握 Windows驱动开发 ...

  2. Windows编程 Windows程序的生与死(下)

    再谈程序之"死" 记得在第二回中我对程序的"死"只是一句话带过,因为我还没有铺垫好,好了现在我们可以详细的分析一下这个过程了. 这还要从while消息循环说起, ...

  3. 驱动中定时器,taskle,工作队列编程

    一.定时器 1.内核时间相关转换函数 unsigned long usecs_to_jiffies(const unsigned int u) 功能: 把微秒转换成时钟节拍 参数: u 时间微秒 返回 ...

  4. C/C++:Windows编程—Windows RPC 传递自定义数据类型、自定义数据类型数组、指针数组

    前言 该篇博文不是讲Windows rpc入门的.是笔者在实际使用Windows RPC时 所遇到的问题,以及解决方法. 笔者有这样的需求,需要从RPC Server获取大量数据,而且该数据是动态分配 ...

  5. Windows编程(2)

    文章目录 windows有关的重要概念 句柄 窗口 Windows的消息机制 消息结构体 宽字符与Unicode 宽字符串的长度 ASCII 和 Unicode 兼容性问题 Windows数据类型 w ...

  6. Linux 设备驱动中的 I/O模型(一)—— 阻塞和非阻塞I/O

    在前面学习网络编程时,曾经学过I/O模型 Linux 系统应用编程--网络编程(I/O模型),下面学习一下I/O模型在设备驱动中的应用. 回顾一下在Unix/Linux下共有五种I/O模型,分别是: ...

  7. Linux 设备驱动中的阻塞与非阻塞 I/O

    阻塞操作是指在执行设备操作时若不能获得资源则挂起进程,直到满足可操作的条件后再进行操作.被挂起的进程进入休眠状态,被从调度器的运行队列移走,直到等待的条件被满足.而非阻塞操作的进程在不能进行设备操作时 ...

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

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

  9. Windows内核驱动中操作文件

    一. 在驱动中使用文件 在Windows执行体中,通过文件对象来代表文件,该文件对象是一种由对象管理器管理的执行体对象.例如:目录也是由文件对象代表的. 内核组件通过对象名来引用文件,即在文件的全路径 ...

最新文章

  1. Zabbix安装配置(CentOS7.3)
  2. 动手动脑——登录界面
  3. 【转】c++重载、覆盖、隐藏——理不清的区别
  4. 跨平台使用exp/imp进行数据库转移时出现丢失对象的原因
  5. 子页面赋值给父页面:window.opener.document.getElementById
  6. spring-chapter02-IoC Container
  7. python中函数的参数传递
  8. 固态硬盘系统经常假死_Win7固态硬盘假死卡顿解决方法
  9. 四川大学计算机学院2020推免公示,2020年四川大学计算机(软件)学院夏令营接收推免生条件...
  10. 单细胞测序流程(二)数据整理
  11. linux 内网gcc版本安装,linux下手动安装/升级GCC到较高版本
  12. GPRS模块(sim900a)联网(PC)测试失败篇
  13. 【Android -- 写作工具】Markdown 图片
  14. 2019牛客暑期多校训练营(第一场)E : ABBA(dp)
  15. Simpsons’ Hidden Talents
  16. Python+Qt抽奖点名工具源码窗体程序
  17. 深度学习:自编码进行模式分类
  18. 汇编语言 -- 计时器/倒计时
  19. 如何更改MFC的项目名称
  20. 2018年7月面试记录

热门文章

  1. Hemberg-lab单细胞转录组数据分析(一)
  2. C4D插件:Springy for Mac 动​​画对象添加重叠动作插件
  3. 《数学与生活》的3本书籍
  4. laravel windos 无法生成 appkey 的问题解决方法
  5. php模拟远程提交get 、post 实例函数
  6. python字符数组输出_python字符串格式化输出
  7. git fetch 与 git pull
  8. 稳压电源的设计与制作_电子爱好设计的直流可调压电源电路,太完美了,有图,亲测可用...
  9. C++工作笔记-多继承下的一个大坑
  10. docker 提交自定义镜像