高分辨率计时器

以前的版本应该是驱动下都可以用高精度,应用态下是低精度;现在变了,应该是微软要把 系统 高精度定时器管控起来,驱动下面也要用特定接口才行。

win10 64位下SetTimer设置的时间与延时的精确度均误差15ms,win10 32位下可以做到2ms精确时间。
修改win10 64位下的时针为高精度定时可以精确到ms。但是高精度定时这个数据类型是win8以后的版本才支持,所以在wdk7600编译都不能识别,把驱动移到VS2019上去编译才可以。编译后的驱动文件win10的32位,64位上面测试都正常了。
win7,32与64们下面使用高精度时钟驱动无法正常加载,设备管理器显示黄色感叹号,显示驱动文件已经被破坏或丢失,错误码39。

这个是为了测试做的延时函数:
void HAL_DelayMs_test (ULONG dwMilliSec)
{
 LARGE_INTEGER Interval;
 ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
 Interval.QuadPart = (LONGLONG)(dwMilliSec);
 Interval.QuadPart *= 10000; // number of 100 ns intervals in 1 ms
 Interval.QuadPart *= -1; // negative value indicates relative wait
 KeDelayExecutionThread( KernelMode,FALSE, &Interval );
}
这是对它的调用
 for( i=0;i<60;i++)
 {
  HAL_DelayMs_test (2);
  KdPrint(("times :%d  \n",i));
 }

通过Dbgview看打印对比看到32位下面是延时了3MS,但是64位下面延时了15或者16MS,这个结果与KeSetTimer是一致的。

64位下面修改2ms的延时为50ms,100ms,1000ms,误差基本上都在15ms左右。

64bits的这个现象,有点象是按照windows的系统时钟在运行,windows的应用程序的定时器时间周期是15ms。

可以用ExSetTimerResolution(10000, TRUE);设置一下windows系统时钟分辨率,这是把整个windows的定时器时钟分辨率提升了,会影响整个系统比较耗电。这么验证一下,说明64bits windows10的timer精度可以很高。

控制计时器准确性

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

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

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

代码部分把以前的定时器部分:

KTIMER              channel0AudioTimer;  //定义DpcTimer定时器

KeInitializeTimer(&devext->channel0AudioTimer);   //初始化定时器对象

KeInitializeDpc( &devext->channel0AudioDpc, channel0AudioDpcRoutine, devext );//初始化DPC对象

void    channel0AudioDpcRoutine(struct _KDPC* p_dpc,PVOID context,PVOID arg1,PVOID arg2);   //Dpc回调函数

KeSetTimer(&devext->channel0AudioTimer,largetime,&devext->channel0AudioDpc);


修改为:

PEX_TIMER                channel0AudioTimer;

devext->channel0AudioTimer = ExAllocateTimer(channel0AudioDpcRoutine, devext,EX_TIMER_HIGH_RESOLUTION);                                            //分配并初始化计时器对象

void    channel0AudioDpcRoutine(PEX_TIMER Timer, PVOID context); //回调函数

{

...       

 PDEVICE_EXTENSION devext = (PDEVICE_EXTENSION)context;

....

}

ExSetTimer(devext->channel0AudioTimer, -30000, 0, NULL);                //设置

如果想要精准的ms级别延时:

ExSetTimerResolution(10000, TRUE); //设置一下windows系统时钟分辨率

        延时应用:
ExSetTimerResolution(0, FAUSE);        //使用完后再取消

你可能感兴趣的:(windows)