從這一篇開始,我們介紹那些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時間管理之定時事件的應用就分析完了。