本发明涉及Windows操作系统的中断处理、高精度定时以及系统软件开发技术领域。更具体地说,本发明涉及一种利用APIC(Advanced Programmable Interrupt Controller)定时器在Windows操作系统环境下实现高精度可调速的定时器的方法。
背景技术:
Windows操作系统为用户提供了三类定时器:WM_TIMER消息定时器、多媒体时钟定时器和高精度时钟定时器。
1)WM_TIMER定时器:WM_TIMER定时器是Windows最基础的定时器,通过SetTimer()进行创建和设定间隔,进而采用KillTimer()进行销毁。WM_TIMER创建后将定时为指定线程发送WM_TIMER消息,并加入消息队列等待处理。WM_TIMER定时器消息是一种低优先级消息,只有当没有更高优先级的消息在线程消息队列中时,WM_TIMER消息才会被投递。同时WM_TIMER定时器精度很低,平均值大约在15ms左右,不具有高精度特性。
2)多媒体时钟定时器:多媒体时钟定时器可以为应用程序提供精度为毫秒的定时事件。使用timeSetEvent()函数注册用回调函数,并可以通过调用timeKillEvent()函数关闭定时器。多媒体时钟定时器最高能够实现最高1ms精度定时,多媒体时钟无法满足高于1ms的定时需求.
3)高精度时钟定时器:当系统中存在高精度性能计数器(High-Resolution Performance Counter)时,应用程序能够采用QueryPerformanceCounter函数实现纳秒级精度的定时。QueryPerformanceCounter内部采用循环制,监测CPU高精度性能计数器的变化,因此该定时器的使用会占用大量CPU资源。
此外,虽然Windows系统所提供的上述三类定时器能够满足特定定时精度的需要,但无法动态调整定时器时间间隔与真实系统时间跨度之间的比例关系,即没有提供动态调整定时器速率的功能。
技术实现要素:
本发明的一个目的是解决上述至少一个问题或缺陷,并提供后面将说明的至少一个优点。
本发明还有一个目的是提供一种Windows操作系统环境下可调速定时器的实现方法,其通过Windows驱动的方式,利用APIC定时器设备,产生百微秒级的时钟信号,实现了最高精度为100微秒的高精度定时器;通过在运行时修改APIC定时器中初始计数寄存器(initial count register)中的数值,完成对定时器时间间隔的动态调整,改变定时器时间间隔与真实系统时间跨度之间的比例关系,实现定时器的可调速功能,解决现有的Windows系统定时器不可调速的问题,解决系统定时器功能固定、速率单一的问题,满足Windows程序在不同环境下的应用需求。
为了实现根据本发明的这些目的和其它优点,提供了一种Windows操作系统环境下可调速定时器的实现方法,包括以下步骤:
步骤一、用户态接口提供:选用APIC定时器,提供一组用户态接口;
步骤二、用户态接口封装:将调速功能和时间相关函数接口封装为动态链接库,供Windows操作系统中的应用程序使用;
步骤三、动态链接库加载:应用程序加载所述动态链接库,实现所述用户态接口的调用;
步骤四、新周期值传入内核:应用程序通过调用所述动态链接库中的用户态接口,将调整后的APIC定时器周期以DeviceIoControl或者共享内存的方式传入内核;
步骤五、APIC定时器周期更改:将所述步骤四调整后的APIC定时器周期赋值给初始计数寄存器,实现APIC定时器的周期调整,其中,初始计数寄存器进行了设置,具体设置包括:初始计数寄存器设定公式:计数值=APIC定时器周期×CPU外频×时间单位/1000,往地址0xFEE00380写入计数值,设置初始计数寄存器。
优选的是,调速功能包括:时间速率控制、定时器时间冻结和解冻功能,时间速率控制实现步骤包括:往地址0xFEE00380中写入利用初始计数寄存器设定公式计算所得计数值即可实现1倍速;往0xFEE00380中写入0.1×计数值即可实现10倍速,往0xFEE00380中写入10×计数值即可实现0.1倍速;定时器时间冻结实现步骤包括:保存地址0xFEE00380中数据并往地址0xFEE00380写入0,设置初始计数寄存器为0;解冻功能实现步骤包括:往地址0xFEE00380写入冻结时保存的数值。
优选的是,所述步骤二中,时间相关函数实现授时功能和任务睡眠功能,授时功能实现步骤包括:通过CreateFile函数加载驱动,通过DeviceIoControl函数或者共享内存获取调度器中的系统时间,返回获取的系统时间;任务睡眠功能实现步骤包括:获取当前线程ThreadId作为后续挂起、唤醒操作的操作对象,计算任务释放时间,将当前任务线程控制块TCB插入让渡队列Yield_List中,其中,任务释放时间=定时器系统时间+睡眠时间。
优选的是,APIC定时器进行了相关设置,具体设置包括:Local APIC含有4个用于产生时钟中断的寄存器:分频寄存器、初始计数寄存器、当前计数寄存器与本地向量表寄存器,分频寄存器用来表示当前系统时间基准和系统总线的倍数关系,将往地址0xFEE003E0写入0xB,将分频寄存器设置为1;APIC定时器的计数模式设置:通过本地向量表寄存器设置为单次模式或者周期模式,此处设置为周期模式,在周期模式下,当前计数寄存器自动从初始计数寄存器载入计数值,然后以总线频率开始递减,当计数达到0时,触发本地向量表寄存器中存储的中断向量并根据中断向量从中断向量表中调用中断处理函数,然后再次载入初始计数寄存器中数值,往地址0xFEE00320写入0x300e2,使其指向对应中断处理函数并设置为周期模式。
优选的是,APIC定时器具有高精度特性,其高精度特性通过以下步骤实现:设置APIC定时器:设置初始计数寄存器、分频寄存器和本地向量表寄存器,使其能产生微秒级的时钟信号供调度器使用;内核态函数接口封装:借助于系统服务描述符表,利用已知的Windows接口特征码,搜索系统内存指令,获取调度器所需的函数地址,并根据系统函数原型,利用内联汇编进行调用,供调度器使用;实现调度器:利用上一步所封装的内核态函数接口,完成调度器的编写,在调度器内维护定时器时间和任务队列。
优选的是,调度器内维护定时器时间和任务队列中,所述调度器实现的具体步骤包括:通过用户态接口将需要周期性唤醒的任务的线程控制块TCB插入让渡队列Yield_List并计算任务唤醒时间;系统时间增加APIC周期时间;遍历让渡队列Yield_List,一旦发现存在任务就通过挂起函数地址挂起该任务,并将该任务线程控制块TCB插入等待队列Waiting_List;遍历等待队列Waiting_List检查是否有任务已经到达唤醒时间,如果到达释放时间,就将该任务线程控制块TCB从等待队列Waiting_List中删除并插入就绪队列Ready_List;遍历就绪队列Ready_List检查是否有任务需要唤醒,一旦队列中存在任务,就通过恢复函数地址将该任务唤醒。
优选的是,挂起函数地址为NtSuspendThread函数地址,恢复函数地址为NtResumeThread函数地址。
优选的是,所述调度器通过APIC定时器产生高精度时钟信号中断插入延迟过程调用DPC来触发。
本发明至少包括以下有益效果:
1、利用APIC定时器实现高精度可调速的定时器,解决现有的Windows系统定时器不可调速的问题,解决系统定时器功能固定、速率单一的问题,满足Windows程序在不同环境下的应用需求;
2、定时器提供一组用户态接口,开发人员在需要调试软件时调用定时器所提供的接口即可,方便使用;
3、利用处理器的APIC定时器产生高精度时钟信号,触发实现的调度器,并通过在用户态动态修改初始计数寄存器数值,在Windows操作系统下实现了一个高精度可调速的定时器,经测试,定时器精度可以达到微秒级,满足大多数Windows系统定时要求,同时定时器实现了0.001倍速到10倍速的速率调整功能,满足应用程序对定时器速率调整的需求。
本发明的其它优点、目标和特征将部分通过下面的说明体现,部分还将通过对本发明的研究和实践而为本领域的技术人员所理解。
附图说明
图1为本发明的一个实施例中Windows操作系统环境下可调速定时器的实现方法的流程示意图;
图2说明的是Windows操作系统环境下可调速定时器的实现方法的软件架构示意图;
图3为调速功能逻辑时间控制程序示意图;
图4说明的是APIC定时器的寄存器设置示意图;
图5说明的是APIC定时器高精度特性实现流程图;
图6说明的是调度器调度流程示意图;
图7说明的是系统服务描述符表示意图。
具体实施方式
下面结合附图对本发明做进一步的详细说明,以令本领域技术人员参照说明书文字能够据以实施。
图1示出了根据本发明的一种实现形式,示出了Windows操作系统环境下可调速定时器的实现方法。其中包括:
步骤一、用户态接口提供:选用APIC定时器,提供一组用户态接口;
步骤二、用户态接口封装:将调速功能和时间相关函数接口封装为动态链接库,供Windows操作系统中的应用程序使用;
步骤三、动态链接库加载:应用程序加载所述动态链接库,实现所述用户态接口的调用;
步骤四、新周期值传入内核:应用程序通过调用所述动态链接库中的用户态接口,将调整后的APIC定时器周期以DeviceIoControl或者共享内存的方式传入内核;
步骤五、APIC定时器周期更改:将所述步骤四调整后的APIC定时器周期赋值给初始计数寄存器,实现APIC定时器的周期调整,其中,初始计数寄存器进行了设置,具体设置包括:初始计数寄存器设定公式:计数值=APIC定时器周期×CPU外频×时间单位/1000,往地址0xFEE00380写入计数值,设置初始计数寄存器。
其中,加载方式和驱动应用程序接口靠Windows操作系统提供。
图2示出了Windows操作系统环境下可调速定时器的实现方法的软件架构示意图,该软件架构包括两个模块:内核驱动部分和用户接口部分。内核驱动部分通过Windows驱动方式加载,负责定时器时间维护与任务队列维护。用户接口部分,负责实现定时器调速功能和相关时间函数接口。
利用处理器的APIC定时器产生高精度时钟信号,触发实现的调度器,并通过在用户态接口把时间输入内核,动态修改初始计数寄存器数值,在Windows操作系统下实现了一个高精度可调速的定时器。经测试,定时器精度可以达到微秒级,满足大多数Windows系统定时要求。同时定时器实现了0.001倍速到10倍速的速率调整功能,满足应用程序对定时器速率调整的需求。
其中,内核态驱动部分实施如下:
1、内核态接口封装
Windows下时间相关操作,例如任务睡眠,必然涉及到线程的挂起和恢复操作。Windows本身并没有直接对外提供内核态的上述API,需要手动查找挂起函数NtSuspendThread和恢复函数NtResumeThread函数地址供调度器使用。
因为Windows用户态函数通过系统服务描述符表(System Service Descriptor Table)对应到内核态函数。利用已知Windows内核态函数特征码,搜索系统内存指令,即可获取到系统内核态函数操作地址。获取到该入口地址后根据系统函数原型,利用内联汇编进行调用,即可完成内核态API的封装。
系统服务描述符表,将ring 3用户态的Win32 API和ring 0内核态的API联系起来,是一个地址索引表。每一个用户态的Win32 API都对应一个特定的服务号,这个服务号作为用户态Win32 API所对应内核态API相对于地址索引基地址的偏移量,如图7所示。
在Windows 7 SP1 x86环境下,系统挂起函数NtSuspendThread和恢复函数NtResumeThread的服务号分别是0x16f和0x130,挂起函数的特征码是0xe8,0x66,0x00,恢复函数特征码是0xe8,0x92,0x06。
2、调度器实现
在定时器中,时间维护和任务队列维护由调度器完成,利用APIC Timer产生高精度时钟信号中断插入DPC延迟过程调用(Deferred Procedure Call)来触发调度器。
调度器实现如下:
1)通过用户态接口将需要周期性唤醒的任务的TCB(Thread Control Block)插入让渡队列Yield_List并计算任务唤醒时间
2)系统时间SystemTime增加APIC周期Time。
3)遍历让渡队列Yield_List,一旦发现存在任务就通过之前获取挂起函数地址挂起该任务,并将该任务TCB插入Waiting_List.
4)遍历等待队列Waiting_List检查是否有任务已经到达唤醒时间。如果到达释放时间,就将该任务TCB从Waiting_List中删除并插入Ready_List。
5)遍历就绪队列Ready_List检查是否有任务需要唤醒,一旦队列中存在任务,就通过之前获取的恢复线程函数地址将该任务唤醒,过程如图6所示。
3、APIC Timer周期设置:
在定时器中,APIC定时器(APIC Timer)负责产生高精度的时钟信号。
Local APIC含有4个用于产生时钟中断的寄存器:
1)分频寄存器(divide configuration register)
2)初始计数寄存器(initial count register)
3)当前计数寄存器(current count register)
4)本地向量表寄存器(LVT register)
设置APIC timer步骤如下:
1)分频寄存器用来表示当前系统时间基准和系统总线的倍数关系,首先将往地址0xFEE003E0写入0xB,将分频寄存器设置为1。
a)APIC Timer初始计数寄存器设定公式如下:
计数值Value=APIC Timer周期Time×CPU外频Frequency×时间单位Type/1000。
2)往地址0xFEE00380写入Value,设置初始计数寄存器。
3)计数器模式可以通过本地向量表寄存器设置为单次模式或者周期模式,此处设置为周期模式。在周期模式下,当前计数寄存器自动从初始计数寄存器载入数值,然后以总线频率开始递减,当计数达到0时,触发本地向量表寄存器中存储的中断向量并根据中断向量从中断向量表中调用中断处理函数,然后再次载入初始计数寄存器中数值。往地址0xFEE00320写入0x300e2,使其指向对应中断处理函数并设置为周期模式。步骤如图4所示。
用户接口部分实施如下:
用户接口实现
在高精度可调速定时器中,用户接口实现调速功能、授时功能和任务睡眠功能。
1)调速功能
调速功能如下:时间速率控制和定时器时间冻结、解冻功能。
1)时间速率控制实现:
a)往地址0xFEE00380中写入利用公式计算所得Value即可实现1倍速。
b)往0xFEE00380中写入0.1*Value即可实现10倍速,10*Value即可实现0.1倍速。
2)冻结功能实现:保存地址0xFEE00380中数据并往地址0xFEE00380写入0,设置初始计数寄存器为0。
3)解冻功能实现:往地址0xFEE00380写入冻结时保存的数值,程序如图3所示。
2)时间相关函数
1)授时功能实现:
a)通过CreateFile函数加载驱动。
b)通过DeviceIoControl函数或者共享内存获取调度器中的SystemTime。
c)返回获取的SystimeTime。
2)任务睡眠功能实现如下:
a)获取当前线程ThreadId作为后续挂起、唤醒操作操作对象。
b)计算任务释放时间ReleaseTime=定时器系统时间SystemTime+睡眠时间SleepTime。
c)将当前任务TCB插入Yield_List队列。
图5示出了APIC定时器高精度特性实现流程图
其高精度特性通过以下步骤实现:
1)设置APIC定时器:设置初始计数寄存器、分频寄存器和本地向量表寄存器,使其能产生微秒级的时钟信号供调度器使用;
2)内核态函数接口封装:借助于系统服务描述符表,利用已知的Windows接口特征码,搜索系统内存指令,获取调度器所需的函数地址,并根据系统函数原型,利用内联汇编进行调用,供调度器使用;
3)实现调度器:利用上一步所封装的内核态函数接口,完成调度器的编写,在调度器内维护定时器时间和任务队列。
这里说明的模块数量和处理规模是用来简化本发明的说明的。对本发明的Windows操作系统环境下可调速定时器的实现方法的应用、修改和变化对本领域的技术人员来说是显而易见的。
如上所述,根据本发明,通过Windows驱动的方式,利用APIC Timer实现高精度可调速的定时器。定时器提供一组用户态接口,开发人员在需要调试软件时调用定时器所提供的接口即可,利用APIC Timer设备,产生百微秒级的时钟信号,实现了最高精度为100微秒的高精度定时器;通过在运行时修改APIC Timer中初始计数寄存器(initial count register)中的数值,完成对定时器时间间隔的动态调整,改变定时器时间间隔与真实系统时间跨度之间的比例关系,实现定时器的可调速功能,以解决现有的Windows系统定时器不可调速的问题,解决系统定时器功能固定、速率单一的问题,满足Windows程序在不同环境下的应用需求。
尽管本发明的实施方案已公开如上,但其并不仅仅限于说明书和实施方式中所列运用。它完全可以被适用于各种适合本发明的领域。对于熟悉本领域的人员而言,可容易地实现另外的修改。因此在不背离权利要求及等同范围所限定的一般概念下,本发明并不限于特定的细节和这里示出与描述的图例。