WDF驱动开发-计时器

WDF可以使用框架的内置计时器支持。 它适用于 Kernel-Mode Driver Framework (KMDF) 驱动程序,以及从版本 2 开始的 User-Mode Driver Framework (UMDF) 驱动程序。

框架提供了一个 计时器对象 ,使驱动程序能够创建计时器。 在驱动程序创建计时器对象并启动计时器的时钟后,框架会在经过指定时间量后调用驱动程序提供的回调函数。 (可选)驱动程序可以设置计时器,以便框架在经过指定时间时重复调用回调函数。

若要创建框架计时器对象,驱动程序必须调用 WdfTimerCreate 方法。 此方法注册 EvtTimerFunc 回调函数和定期时间间隔。 如果希望框架只调用回调函数一次,驱动程序会为定期时间间隔指定零。

通常,你将知道驱动程序需要为每个设备使用的计时器数。 因此,驱动程序可以通过在其 EvtDriverDeviceAdd 回调函数中调用 WdfTimerCreate 来创建计时器对象,并且可以将计时器对象句柄存储在设备或队列对象的上下文空间中。

若要启动计时器,驱动程序会调用 WdfTimerStart,传递“到期时间”。 框架启动计时器的时钟,并在指定的时间量已过时调用 EvtTimerFunc 回调函数。

如果驱动程序在调用 WdfTimerCreate 时提供了定期时间间隔,则计时器称为 定期计时器。 在初始“到期时间”过后,定期计时器的时钟将继续运行,并且每当经过定期时间间隔时,框架会重复调用驱动程序的回调函数。 定期计时器不会自动启动。 与非定期计时器一样,驱动程序在创建计时器后仍必须调用 WdfTimerStart ,以便第一次启动它。

驱动程序可能从其 EvtTimerFunc 回调函数调用 WdfTimerStart,以便在非定期计时器过期后重新启动它。

若要停止计时器,驱动程序可以调用 WdfTimerStop。 驱动程序可以通过重复启动和停止计时器来重复使用计时器。

驱动程序创建计时器对象时,必须指定父对象。 框架在删除父级时停止计时器并删除计时器对象。 若要获取计时器对象的父对象,驱动程序可以调用 WdfTimerGetParentObject。

在版本 1.9 之前的 KMDF 版本中,如果希望驱动程序的所有回调函数在 IRQL = PASSIVE_LEVEL 运行,则无法轻松使用计时器对象。 框架将计时器对象的 EvtTimerFunc 回调函数实现为延迟过程调用, 在 IRQL = DISPATCH_LEVEL调用的 DPC。 因此,如果希望计时器过期代码在PASSIVE_LEVEL 则 EvtTimerFunc 回调函数必须将在 PASSIVE_LEVEL 运行 的工作项 排队。

在 KMDF 版本 1.9 及更高版本中,可以创建 被动级别计时器,即在 PASSIVE_LEVEL 运行的计时器。 若要创建被动级别计时器,请在驱动程序调用 WdfTimerCreate 时指定 WdfExecutionLevelPassive 执行级别。 因此,框架将 EvtTimerFunc 回调函数实现为在PASSIVE_LEVEL运行的工作项。 请注意,被动级别计时器不能是定期计时器。

从 UMDF 版本 2.0 开始,框架将计时器对象的 EvtTimerFunc 回调函数实现为用户模式线程池中的工作线程。 因此,UMDF 驱动程序的计时器回调函数始终在PASSIVE_LEVEL运行。

无唤醒计时器

反复导致系统从低功耗状态恢复的计时器会降低系统电源效率。 延长电池使用时间的一种方法是延迟非关键定期操作,而不是唤醒系统。 从 Windows 8.1 开始,可以使用任何唤醒计时器在 KMDF 或 UMDF 驱动程序中执行此类非关键操作。 当系统处于低功耗状态时,无唤醒计时器不会唤醒系统。 相反,当系统下次完全处于 S0 状态时,框架会调用驱动程序的 EvtTimerFunc 回调函数。

从 KMDF 版本 1.13 和 UMDF 版本 2.0 开始,没有可用的唤醒计时器。

若要创建无唤醒计时器,请将 WDF_TIMER_CONFIG 的 TolerableDelay 成员设置为 TolerableDelayUnlimited。

高分辨率计时器

标准框架计时器的准确度与系统时钟计时周期间隔匹配,默认情况下为 15.6 毫秒。 从 Windows 8.1 开始,可以创建高分辨率计时器。 高分辨率计时器的准确度为 1 毫秒。 对于需要精确、可预测的过期时间的关键操作,可以使用高分辨率计时器。 由于需要频繁维护,高分辨率计时器可能会导致电池使用时间缩短。

高分辨率计时器仅适用于 KMDF 驱动程序,从 KMDF 版本 1.13 开始。

若要创建高分辨率计时器,请将 WDF_TIMER_CONFIG 的 UseHighResolutionTimer 成员设置为 WdfTrue,然后将 Period 值调整为所需的分辨率。

下表显示了基于驱动程序为 Period 提供的不同值的计时器行为示例。 这些示例假定系统时钟计时周期间隔为 15 毫秒:

更准确的描述见本文的下半部分描述。 

计时器准确性

系统计时器例程通常允许调用方指定计时器的绝对或相对过期时间。 例如 KeWaitForSingleObject、 KeSetTimer 或 KeDelayExecutionThread。 操作系统测量过期时间的准确度受系统时钟粒度的限制。

系统时间在系统时钟的每个时钟周期上更新,并且仅精确到最新的时钟周期。 如果调用方指定绝对过期时间,则会在处理指定时间后发生的第一个系统时钟时钟周期期间检测到计时器的过期时间。 因此,计时器可以比指定的绝对过期时间晚一个系统时钟周期。 如果指定了计时器间隔或相对过期时间,则到期时间可能早于指定时间或晚于指定时间,具体取决于此间隔的开始和结束时间在系统时钟周期之间的确切位置。 无论指定的是绝对时间还是相对时间,如果系统时钟的中断处理因其他设备的中断处理而延迟,则直到以后才检测到计时器过期。

当调用方指定相对过期时间时,计时器例程会将当前系统时钟时间添加到指定的相对过期时间,以计算计时器使用的绝对过期时间。 由于系统时间仅精确到系统时钟的最新时钟周期,因此计算的过期时间最多可以早于调用方预期的过期时间的系统时钟周期。 如果指定的相对过期时间接近或小于系统时钟周期,计时器可能会立即过期,不会延迟。

更准确地支持较短过期时间的一种可能方法是缩短系统时钟周期之间的时间,但这样做可能会增加功耗。 此外,缩短系统时钟周期可能无法可靠地实现更精细的系统时钟粒度,除非可以保证平台中其他设备的中断处理不会延迟系统时钟中断的处理。

从Windows 8开始,KeDelayExecutionThread 使用更精确的技术从调用方指定的相对过期时间计算绝对过期时间。 首先,为了更准确地估计当前系统时间,例程使用系统性能计数器来测量自上次系统时钟计时周期以来经过的时间。 接下来,例程将系统时间的此更精确的估计值添加到相对过期时间,以计算绝对过期时间。 此方法计算的绝对过期时间精确到微秒内。 因此,计时器不会在指定的相对过期时间之前过期。 计时器仍可能过期到系统时钟周期晚于指定时间,并且即使系统时钟中断的处理因其他设备的中断处理而延迟,也可能在以后过期。

如果系统时间在计时器过期之前发生更改,则相对计时器不受影响,但系统会调整每个绝对计时器。 相对计时器始终在指定的时间单位数过后过期,而不考虑绝对系统时间。 绝对计时器在特定系统时间过期,因此系统时间的更改会更改绝对计时器的等待持续时间。

高解析度计时器

从 Windows 8.1 开始,驱动程序可以使用 ExXxx计时器例程来管理高分辨率计时器。 高分辨率计时器的准确性仅受系统时钟支持的最大分辨率的限制。 相比之下,限制为默认系统时钟分辨率的计时器的准确度明显较低。

但是,高分辨率计时器需要系统时钟中断(至少暂时)以更高的速率发生,这往往会增加功耗。 因此,驱动程序应仅在计时器准确性至关重要时才使用高分辨率计时器,并在所有其他情况下使用默认分辨率计时器。

为了创建高分辨率计时器,WDM 驱动程序调用 ExAllocateTimer 例程并在 Attributes 参数中设置EX_TIMER_HIGH_RESOLUTION标志。 当驱动程序调用 ExSetTimer 例程来设置高分辨率计时器时,操作系统会根据需要增加系统时钟的分辨率,以便计时器过期的时间更准确地对应于 DueTime 和 Period 参数中指定的名义过期时间。

Kernel-Mode驱动程序框架 (KMDF) 驱动程序可以调用 WdfTimerCreate 方法来创建高分辨率计时器。 在此调用中,驱动程序将指向 WDF_TIMER_CONFIG 结构的指针作为参数传递。 若要创建高分辨率计时器,驱动程序会将此结构的 UseHighResolutionTimer 成员设置为 TRUE。 从 Windows 8.1 和 KMDF 版本 1.13 开始,此成员是结构的一部分。

控制计时器准确性

例如,对于在 x86 处理器上运行的 Windows,系统时钟周期之间的默认间隔通常约为 15 毫秒,系统时钟周期之间的最小间隔约为 1 毫秒。 因此,如果未设置EX_TIMER_HIGH_RESOLUTION标志 (, 则 exAllocateTimer 创建的默认分辨率计时器的过期时间) 只能控制在大约 15 毫秒内,但高分辨率计时器的过期时间可以控制在一毫秒内。

如果驱动程序为默认分辨率计时器指定相对过期时间,则计时器最多可以早于或晚于指定的过期时间约 15 毫秒。 如果驱动程序为高分辨率计时器指定相对过期时间,则计时器的过期时间可能晚于指定过期时间后大约一毫秒,但它永远不会提前过期。 

如果未设置高分辨率计时器,操作系统通常按其默认速率运行系统时钟。 但是,如果设置了一个或多个高分辨率计时器,则操作系统可能需要在其最大速率下运行系统时钟至少一部分时间,然后这些计时器才会过期。

为了避免不必要地增加功耗,操作系统仅在需要满足高分辨率计时器的计时要求时才以最大速率运行系统时钟。 例如,如果高分辨率计时器是周期性的,并且其周期跨越多个默认的系统时钟时钟周期,则操作系统可能仅在每次到期前的计时器时间段内以最大速率运行系统时钟。 在计时器的剩余时间内,系统时钟按其默认速率运行。

为防止过度耗电量,驱动程序应避免将长时间运行的高分辨率计时器的时间段设置为小于系统时钟周期之间的默认间隔的值。 否则,操作系统将被迫以其最大速率连续运行系统时钟。

从 Windows 8 开始,驱动程序可以调用 ExQueryTimerResolution 例程来获取系统时钟支持的计时器分辨率范围。

与 ExSetTimerResolution 的比较

从 Windows 2000 开始,驱动程序可以调用 ExSetTimerResolution 例程来更改连续系统时钟中断之间的时间间隔。 例如,驱动程序可以调用此例程,将系统时钟从默认速率更改为最大速率,以提高计时器准确性。 但是,与使用 ExAllocateTimer 创建的高分辨率计时器相比,使用 ExSetTimerResolution 有几个缺点。

首先,在调用 ExSetTimerResolution 以暂时提高系统时钟速率后,驱动程序必须再次调用 ExSetTimerResolution 才能将系统时钟还原到其默认速率。 否则,系统时钟计时器会以最大速率持续生成中断,这可能会导致过度的功耗。

其次,使用 ExSetTimerResolution 例程 的驱动程序无法像操作系统对高分辨率计时器那样有效地优化对更高系统时钟速率的临时使用。 因此,系统时钟以最大速率运行的时间比严格必要的时间要多。

第三,如果多个驱动程序同时使用 ExSetTimerResolution 来提高计时器准确性,则系统时钟可能会长时间以最大速率运行。 相比之下,操作系统全局协调多个高分辨率计时器的操作,以便系统时钟仅在需要满足这些计时器的计时要求时才以最大速率运行。

最后,使用 ExSetTimerResolution 本质上不如使用高分辨率计时器准确。 在驱动程序调用 ExSetTimerResolution 将系统时钟增加到其最大速率(通常为每毫秒一个时钟周期)后,驱动程序可能会调用 KeSetTimerEx 等例程来设置计时器。 如果在此调用中,驱动程序指定相对过期时间,则计时器最多可以早于或晚于指定的过期时间约一毫秒。 但是,如果为高分辨率计时器指定了相对过期时间,则计时器可能比指定的过期时间晚大约一毫秒,但它永远不会提前过期。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/724853.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Scala语言:大数据开发的未来之星 - 零基础到精通入门指南

前言 随着大数据时代的到来,数据量的急剧增长为软件开发带来了新的挑战和机遇。Scala语言因其函数式编程和面向对象的特性,以及与Apache Spark的完美协作,在大数据开发领域迅速崛起,成为该领域的新兴宠儿。本篇将从零基础开始&…

Vue59-全局事件总线:任意组件间通信

一、原理图 只是总结出的经验,不是新的API! 二、x的要求: 1、保证x被所有组件看见; 2、x可以调用的到$on,才能绑定事件,还能调用到:$of, $emit; 三、x的创建&#xff…

手把手教你创建并启动一个Vue3项目(Windows版)

一、Node安装 1、下载地址:Node.js — Run JavaScript Everywhere 2、安装Node,双击启动一直Next 3、验证安装Node是否成功,打开CMD命令窗口,输入node -v,显示版本就表示成功 4、验证安装npm是否成功,npm是…

sqlite3指令操作-linux

1.查看当前数据库位置 2.查看当前数据库文件下有哪些表 3.显示 某表创建时的SQL语句 4.打开、关闭显示列标题; 5.列对齐显示 6.列以‘,’分隔显示 .separator 7.查询表信息 8.插入消息 9.删除某一行内容 10.修改某行某列内容 11.修改表名字 alter tab…

开发者黑板报#65

第65期 AI 谷歌Gemini 终于,GPT-4独霸时代终结了! 过去一个月里,四款大模型横空出世,在各项关键基准测试中与GPT-4相匹敌,甚至更胜一筹。 谷歌Gemini 1.5突破100万个tokens,是GPT-4的近8倍&#xff0c…

办公楼导航系统:设计要点、功能实现与效益评估

随着现代办公楼的日益复杂化和规模化,如何高效、便捷地在楼宇内部进行定位和导航,已成为众多企业和员工关注的焦点。维小帮办公楼定位导航系统通过精准的定位和智能的导航功能,能够显著提升办公环境的智能化水平和办公效率。 一、维小帮办公…

嵌入式实验---实验一 通用GPIO实验

一、实验目的 1、掌握STM32F103 GPIO程序设计流程; 2、熟悉STM32固件库的基本使用。 二、实验原理 1、通过按键实现:按键按下,LED点亮;按键释放,LED熄灭。 三、实验设备和器材 电脑、Keil uVision5软件、Proteus…

Top10在线音频剪辑软件,你了解几款?(免费分享)

多年来,随着音乐制作人和音频工程师的需求不断增长,音频剪辑软件领域经历了巨大的发展。最新的音频剪辑软件提供了从基本录制到最终发布所需的一切功能。其中一些软件专为播客设计,一些软件是免费的,并且一些软件提供了出色的音效…

【Win】双系统新体验:Hyper-V上macOS安装攻略

在虚拟化的世界里,Hyper-V是探索不同操作系统的一扇大门。尽管macOS并不是Hyper-V官方支持的来宾操作系统,但这并未阻挡技术探索者的脚步。他们通过不懈努力,开辟出了一条条通往macOS的非官方路径。这些路径或许曲折,却为那些渴望…

Z世代职场价值观的重塑:从“班味”心态到个人成长的追求

近日,社交平台Soul APP联合上海市精神卫生中心(俗称“宛平南路600号”)发布《2024年Z世代职场心理健康报告》(下称“报告”),发现今天的年轻人正以其独特的价值观和行为模式,重新定义成功与成就…

机器学习_SVM支持向量机

引入:在面对线性可分时,即用一条直线就可以区分数据的时候,需要将直线放在距离数据点距离最大化的位置,这个过程需要寻找最大间隔,即为最优化问题。当数据点不能用一根直线区分——线性不可分,就需要用核函…

瑞数信息入选IDC《中国WAAP厂商技术能力评估,2024》

5星满分:WAF、Bot流量管理、行业应用等评估维度 日前,全球领先的IT市场研究和咨询公司IDC发布《中国WAAP厂商技术能力评估,2024》。报告聚焦WAAP能力,通过对中国市场中主要WAAP产品提供商的技术评估以及对大量最终用户的客观访谈…

SpringBoot配置第三方专业缓存技术Ehcache

Ehcache缓存技术 我们刚才是用Springboot提供的默认缓存技术 我们用的是simple 是一个内存级的缓存 我们接下来要使用专业的缓存技术了 Ehcache 是一个流行的开源 Java 分布式缓存,由 Terracotta 公司开发和维护。它提供了一个快速、可扩展、易于集成的内存缓存…

【LeetCode最详尽解答】11-盛最多水的容器 Container-With-Most-Water

欢迎收藏Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog。如果收藏star, 有问题可以随时与我交流, 谢谢大家! 链接: 11-盛最多水的容器 直觉 这个问题可以通过可视化图表来理解和解决。 通过图形化这个…

防止员工离职导致数据泄露,员工离职后把文件带出公司

中科数安的电脑文件资料透明加密防泄密系统确实能够在一定程度上防止员工离职导致的数据泄露。以下是具体的分析: www.weaem.com 访问控制与权限管理:系统实施了严格的权限管理制度,对核心文件和数据资源进行细致的访问权限划分。这意味着&am…

从零开始! Jupyter Notebook的安装教程

🚀 从零开始! Jupyter Notebook的安装教程 摘要 📄 Jupyter Notebook 是一个广受欢迎的开源工具,特别适合数据科学和机器学习的开发者使用。本文将详细介绍从零开始安装 Jupyter Notebook 的步骤,包括各种操作系统的安装方法&am…

大屏适配方案汇总

1. 适配方案1:rem font-size 我们都知道,在 css 中 1rem 等于 html 根元素设定的 font-size 的 px 值,通过动态的修改html 根元素的 font-size 大小就能动态的改变 rem 的大小,从而实现适配。 原理 动态设置 HTML 根字体大小将…

产品交付能力提升的探索与分享

在当前激励的市场竞争环境下,对项目交付的成本和毛利要求越来越高。如何能快速高效地完成项目交付已然成为我们矢志追求的目标。抛开人为因素对项目交付效率的影响,产品本身的交付能力才是关键。因此,在设计新产品时需要考虑其便捷交付性&…

Linux下调试代码——gdb的使用

1. 文件准备: 测试代码: Makefile文件: 执行结果: 此时,我们的结果是存在问题的,即最终结果少了100。现在我们用gdb来调试它。 我们发现我们还没有安装gdb,这里安装一下。 2. 环境准备&#…

Inno Setup 打包java程序

Inno Setup工具打包java程序(包括mysql) 一:准备安装工具(点击即下载) 1.innosetup 2.battoexe 二:需要打包的内容放同一个文件夹 三.使用battoexe将.bat文件转变为.exe文件 转后的.exe放在同个文件夹 四.使用innosetup进行…