从这一篇开始,我们介绍那些QF系统框架提供给我们的服务,QF这里称为一个系统框架,其实你可以理解为它为了适配状态机而提供的一些必要服务,针对操作系统进行也一些裁剪,时间管理这个概念在操作系统中应用的更加广泛,例如任务时间片分配,任务睡眠,唤醒这些都是基于强大的时间管理,系统心跳为这一切提供强大的支持,在QF中时间管理的一大核心任务就是为【定时事件】服务。
因为基于事件驱动型系统的核心之一就是【事件】,事件又被分为了两种,一种为普通事件、一种叫做定时事件。普通事件相对来讲比较简单,它所处理的事件都是实时的(换句话说随时可能发生),而还有一种情况需要在给定的时间发送事件,这种叫做定时事件。
定时事件 = 普通事件 + 闹钟(定时机制)。
用一张结构定义图来分析他们之间的关系,如下:
这里我们不再讲普通事件涉及的内容,虽然简单,留到后面讲事件队列的时候一起讲比较合适,不管普通事件还是定时事件,本质都是事件,对于状态机而言,他们都需要事件队列的支持。这里我会站在应用的角度上来分析一下定时功能,当然也会涉及一部分底层的实现,但是尽量不讲,学习的时候一定要分清自己的目的,你是想要学会如何应用QF系统框架,还是重写一个系统框架,扯远了。。。
要应用事件的定时功能,主要涉及框架提供的几个接口操作:
1. postIn()提供单次定时功能。
2. postEvery()提供周期性定时功能。
3. disarm()提供相应定时功能的解除。
关于定时功能的理解,其实有个很简单的方式,掏出你的手机,打开你的闹钟,设定一个闹钟,设置过程他会提示你 仅响铃一次,还是循环定时,同样在你设定了闹钟以后,在定时事件没到之前,你可以随时取消闹钟,就是我们的disarm(),这里都是介绍的这几个功能原型,真正的API可能并不是这样,也有可能被定义成了一个宏。
系统心跳systemtick,这个词我相信你在操作系统领域听得耳朵都有点长茧子了,要实现上面的定时功能, 需要设置一个系统心跳,系统时钟街拍是一个以预先确定的速率发生的周期性中断(这里指的是硬件中断,后面会介绍一种新的软中断),典型的速率在10到100hz之间,实际的频率取决你的应用所需的最小时基,节拍的速率并不是越快越好,越快代表着更多的时间管理开销(管理开销会导致你的定时时间的误差,主频更快的CPU可以消解这种误差的大小,但是我们的CPU受制于成本不可能无限的快)。
时间事件在应用时需要注意以下几点:
1. 时间事件必须是静态的,不能是动态的(事件从定义的方式来讲可以分为静态和动态两种),这里遵守就好了。
2. 一个时间事件在实例化时,必须分配一个信号,并且这个信号不能被改变。
下面以QPC6.9.1版本源码为基础,以dpp为例从真实的角度来介绍一下其应用,首先看一下时间事件的定义及接口函数,以一个应用为例讲一下如何应用事件事件服务于我们的状态机,先看一下定义:
接口函数部分是重点,因为真正在应用程序中需要应用他们,如下:
针对这些常用的API函数,我们需要详细了解他们的参数才能更好的使用他们,如下:
还剩下两个不怎么常用的函数,就不介绍了,等你用到的时候可以自己去翻看一下源码,QP一个很强的设定是不怎么需要API参考手册,因为就这清晰的注释可以帮你看透一切。
如何在实际中去使用定时事件才是我们最终的目的,关于使用我们以dpp为例,分了几个步骤来使用,如下:
【第一步】定义事件对象结构并实例化它。
【第二步】 在活动对象构造时,调用相应的定时事件构造函数。
【第三步】在状态处理过程中,启动定时器(最常用的方式)。
总结一下,在实际应用时,需要特别注意两个点,应用环境(位置)和调用参数设定。整个QF定时事件的功能,都是依赖于QF_tick,在这里并没有讲如何设置该函数,因为它与移植有关。
到这里关于QF时间管理之定时事件的应用就分析完了。