如何访问/查询Windows计时器解析管理信息?

时间:2014-05-19 09:56:47

标签: windows winapi

此问题的灵感来自SO问题How to tell which process set the high timer resolution in Windows?How does powercfg -energy detect the requested timer resolution?以及仔细调查。

后台: Windows允许通过函数timeBeginPeriod / timeEndPeriod或基础NtSetTimerResolution(由ntdll.dll导出)修改系统计时器分辨率)。允许任何进程获取平台支持的计时器分辨率。计时器分辨率是全局设置,Windows使用任何进程请求的最高分辨率。此计时器分辨率设置的全局性质需要内部数据结构来跟踪哪个进程已获得哪个分辨率。使用 SetResolution = TRUE 调用timeBeginPeriod或NtSetTimerResolution将在该数据结构中注册一个条目。随后使用 SetResolution = FALSE 调用timeEndPeriod或NtSetTimerResolution将删除该条目。 当删除条目并且获取的计时器分辨率是当前支持的最高分辨率时,系统将计算出下一个最高注册分辨率,并相应地设置计时器分辨率。下一个最高分辨率可能小于或等于当前最高分辨率。有关详细信息,请参阅MSDN: Timer Resolution


上面提到的鼓舞人心的问题是询问有关访问此管理数据结构的API,特别是关于哪些进程获得了哪些计时器分辨率,甚至只有哪个进程获得了当前分辨率。

在此问题上工作一段时间后,我们有理由相信必须有办法获取这些信息:

支持的分辨率取决于Windows的版本和硬件平台。有些分辨率是典型的,其他分辨率似乎奇数因为它们几乎不出现。可以通过调用timeBeginPeriod(uPeriod)来增加 uPeriod 的值(通常范围从1到16)来获得支持的分辨率列表。

在XP / VISTA / 7上将定时器分辨率设置为这些奇数分辨率之一可能会导致分辨率自发变化,但不一定立即变为特定平台上更常见的分辨率。首先想到的是,这可能是另一个应用程序或驱动程序,它只是不喜欢这个特殊的奇怪分辨率。因此,可疑进程/驱动程序将更改计时器分辨率以更好地满足其要求。但是,这只能朝一个方向发展;进程/驱动程序只能通过选择更高的分辨率来修改计时器分辨率。到现在为止还挺好。但是现在如果无法查询数据结构,系统应该停留在该分辨率上。将禁止更改为较低分辨率。

当从列表中取出奇数分辨率时,例如通过调用timeEndPeriod,分辨率应保持在可疑进程/驱动程序设置为不喜欢奇数分辨率的位置。

但事实并非如此!分辨率返回到较低的分辨率。进程/驱动程序必须已经知道奇数解析未注册的事实,并且它也发布了注册。然而,更详细的调查表明它不会异步通知,一些延迟表明可疑进程/驱动程序可能经常监视实际的计时器分辨率数据结构。

问题:如何访问此数据结构?

注意:很可能是内核本身。但很难相信Windows本身会自发地改变“不喜欢”的计时器分辨率。

更新 Code Machine:关键Windows内核数据结构的目录:内核变量ExpTimerResolutionListHead维护一个已调用NtSetTimerResolution()以更改计时器间隔的进程列表。 ExpUpdateTimerResolution()使用此列表将时间分辨率更新为所有进程中的最低请求值。

任何想法如何访问内核数据结构ExpTimerResolutionListHead,而不是使用LifeKD或其他方式进行内核模式调试,如David Solomon和Mark Russinovich在“Windows Internals Part 1,6th Edition”中所述, Microsoft Press 2012?

0 个答案:

没有答案