首页 理论教育 操作系统实现之路:设置定时器操作

操作系统实现之路:设置定时器操作

时间:2023-10-21 理论教育 版权反馈
【摘要】:在当前版本Hello China的实现中,定时器服务接口集成在System对象里面,这样主要是考虑到实现上的方便。在System的定义中,定义了一个定时器对象队列用来维护定时器对象,并定义了三个定时器对象操作接口。SetTimer调用可以用来设定一个定时器对象,该函数操作过程如下。初始化该定时器对象。第一个问题是,如何确定该定时器对象的超时时刻。dwPriority大于dwNextTimerTick,说明先前已经有定时器被设置,而且设置的定时器超时时间比当前设置的要提前。

操作系统实现之路:设置定时器操作

在当前版本Hello China的实现中,定时器服务接口集成在System对象里面(另外与中断有关的操作等,也是作为System对象接口来提供),这样主要是考虑到实现上的方便。在System的定义中,定义了一个定时器对象队列用来维护定时器对象,并定义了三个定时器对象操作接口。下面是System对象定义的相关部分代码。

可以看出,lpTimerQueue用来维护定时器对象,SetTimer、CancelTimer和ResetTimer分别对应前面介绍的三个系统调用(在转换为系统调用的时候,省略前两个参数lpSystem和lpKernelThread,因为系统中只有一个System全局对象,所以缺省情况下,取系统中这个全局对象为第一个参数,调用该函数的当前线程为第二个参数)。

SetTimer调用可以用来设定一个定时器对象,该函数操作过程如下。

(1)调用CreateObject(ObjectManager对象提供的接口)函数创建一个定时器对象。

(2)初始化该定时器对象(根据用户传递过来的参数)。

(3)把定时器对象插入定时器对象维护队列。

(4)重新设定调度时刻。(www.xing528.com)

这里有两个问题需要说明一下。

第一个问题是,如何确定该定时器对象的超时时刻。在当前版本的实现中,定时器的超时判断是在时钟中断处理程序里进行的,系统维护一个全局变量dwClockTickCounter用来记录时钟中断数量,即每发生一次时钟中断,该变量递增一,同样地,系统也维护了另外一个变量dwNextTimerTick用来表示下一个定时器超时时的时钟中断个数,这样每次时钟中断的时候,中断处理程序就会比较这两个变量,如果这两个变量相同,则说明在这个时钟中断中有至少一个定时器对象超时了,因此需要做进一步处理。对dwNextTimerTick变量的设置是这样进行的(在SetTimer函数调用中):

其中,dwPriority是一个临时变量,SYSTEM_TIME_SLICE是系统定义的时间片,即每个时钟中断之间的时间间隔(以毫秒为单位,当前定义为55)。上述处理中,首先把dwTimeSpan(定时器设定的等待时间,单位为毫秒)换算成时钟中断个数(tick个数),然后与当前tick计数(dwClockTickCounter)相加,这样就得到了当前定时器超时时的tick。所有这些完成之后,再与dwNextTimerTick比较,如果小于dwNextTimerTick,则设置当前dwNextTimerTick为dwPriority,否则,保留dwNextTimerTick不变。dwPriority大于dwNextTimerTick,说明先前已经有定时器被设置,而且设置的定时器超时时间比当前设置的要提前。

第二个问题是,定时器维护队列(lpTimerQueue)是一个优先队列,在插入该队列的时候,可以提供一个优先数值,让队列确定插入对象应该在的位置,优先级越高,对象在优先队列中的位置越靠前。对于定时器对象,理想的处理方式是,离超时时刻越近,应该越提前,但这样跟优先队列的优先级确定方式刚好相反(优先级越大,越靠前),所以,为了把最先超时的定时器对象插入优先队列的最前面,可采用下列方式:

其中,lpTimerObject是SetTimer创建的定时器对象,而MAX_DWORD_VALUE则是一个最大的类型为DWORD的常数,在32位硬件平台上,定义为0xFFFFFFFF,这样变换之后,就可以实现上述目的(即把最先超时的对象,插入优先队列的最前端)。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈