如何調(diào)整事件隊(duì)列和事件池的大???
我們只有一個目標(biāo),為了最小化這個內(nèi)存。最小化帶來的風(fēng)險,隊(duì)列溢出或者內(nèi)存池被耗光,斷言失敗,這兩種情況被歸為第一類故障,同為第一類故障的還有堆棧溢出。
在開發(fā)初期使用超大型的事件隊(duì)列和內(nèi)存池,讓你的開發(fā)更具有靈活性,調(diào)整事件隊(duì)列和事件池放在開發(fā)的末尾。這并不意味著在設(shè)計(jì)過程中,完全不在乎隊(duì)列和內(nèi)存池。
在設(shè)計(jì)的時候一定要遵從一般性規(guī)則,什么是一般性規(guī)則,舉個類比你就明白了:在我們的單片機(jī)的啟動代碼中需要定義一個堆棧,經(jīng)典的0x400,如何避免棧溢出?
答:一般性規(guī)則,避免函數(shù)的深度嵌套和大的自動變量。
在我們QF中,同樣定義了一個定量的事件隊(duì)列和內(nèi)存池,如何避免他們溢出?
答:一般性規(guī)則,避免不必要的事件產(chǎn)生或把較長的RTC步驟分解。
關(guān)于事件隊(duì)列你需要理解一個事實(shí):平均事件產(chǎn)生速率 不能超過 平均事件消耗速率,假如這一個規(guī)則被打破,再大的隊(duì)列也會被撐爆,只是時間問題。但是偶爾產(chǎn)生率可以超過消耗速率,但不能持續(xù)很長時間類似我們CPU的超頻功能。
傳統(tǒng)的確認(rèn)事件隊(duì)列或內(nèi)存池使用量有兩種方式,第一種較為簡單就是通過運(yùn)行時觀察系統(tǒng)動態(tài)實(shí)時開銷來評估需要多少的內(nèi)存,像QF在事件隊(duì)列中提供nMin(數(shù)據(jù)成員)。
靜態(tài)內(nèi)存分析是我們提高軟件設(shè)計(jì)能力的核心,動態(tài)分析往往作為輔助驗(yàn)證。
一下幾種情況可以當(dāng)做小故事來思考,幫你理解靜態(tài)分析的核心:(出自QP原書實(shí)例):考慮某個 QF 應(yīng)用程序運(yùn)行在某個可搶占的,基于優(yōu)先級的內(nèi)核上 。假設(shè)最高優(yōu)先級 的活動對象僅接受其他活動對象的事件(但是不結(jié)束從 ISR 發(fā)出的事件)。每當(dāng)任何低優(yōu)先級的活動對象發(fā)送或發(fā)行某個事件給最高優(yōu)先級的對象,內(nèi)核立即把 CPU賦給接收者。內(nèi)核做這個上下文切換是因?yàn)?,在這一刻,接收者是最高優(yōu)先級的預(yù)報運(yùn)行的線程。最高優(yōu)先級的活動對象醒過來,并運(yùn)行到結(jié)束, 消耗任何發(fā)送給它的事件。因此,最高優(yōu)先級的活動對象實(shí)際不需要對事件排隊(duì)(它的事件隊(duì)列的最大 深度為 1 ) 當(dāng)最高優(yōu)先級的活動對象接受從 ISR 來的事件時,更多的事件會為了它排隊(duì)。
在最常見的安排中, 某個 ISR 每次活動時僅產(chǎn)生一個事件。另外,實(shí)時要求的底線通常是,最高優(yōu)先級的活動對象必須在下個中斷前消耗完事件。這種情況下,活動對象的事件隊(duì)列可以增長到最多 2 個事件:一個用于任務(wù),另一個用于某個 ISR 。你可以把這個分析遞歸的擴(kuò)展到較低優(yōu)先級的活動對象。被排隊(duì)的事件的最大數(shù)量是,在給定的底線內(nèi),所有可以為這個活動對象產(chǎn)生事件的較高優(yōu)先級線程和 ISR 產(chǎn)生的所有事件的總和。底線時這個活動對象的最長的 RTC步驟,包括所有可能的來自較高優(yōu)先級線程和 ISR 的搶占。例如,在 DPP應(yīng)用程序中,所有 Philosoper活動對象執(zhí)行非常少的處理(它們有短的 RTC步驟)。如果 CPU可以在一個時鐘節(jié)拍內(nèi)完成這些 RTC步驟, Philosopher 隊(duì)列的最大長度將是 3 個事件:一個用于系統(tǒng)時鐘ISR ,其它 2 個用于活動對象 Table ( Table 有時候在一個 RTC步驟內(nèi)發(fā)行 2 個事件)。
對事件隊(duì)列進(jìn)行靜態(tài)分析的經(jīng)驗(yàn)參考如下:
1. 事件隊(duì)列的大小取決于活動對象的優(yōu)先級。一般的,優(yōu)先級越高,必需的事件隊(duì)列越短。特別的,系統(tǒng)里最高優(yōu)先級活動對象立即消耗所有被其他活動對象發(fā)現(xiàn)的所有事件,僅需要對那些被 ISR 發(fā)行的事件進(jìn)行排隊(duì)。
2. 隊(duì)列尺寸取決于最長的 RTC步驟持續(xù)的時間,包括所欲可能的(最差情況下的)來自較高優(yōu)先級活動對象或 ISR 的搶占。處理越快,必需的事件隊(duì)列越短。為了最小化隊(duì)列尺寸, 你應(yīng)該避免非常長的 RTC步驟。理想情況是,某個給定活動對象的所有 RTC步驟都只需要相同的 CPU周期來完成。
3.任何相關(guān)的事件生產(chǎn)都能增加隊(duì)列的尺寸。例如,有時候 ISR 或活動對象在一個 RTC步驟內(nèi)生產(chǎn)多個事件實(shí)例(例如, Table 活動對象偶爾生產(chǎn) 2 個就餐許可事件)。如果在你的應(yīng)用程序中,最小的隊(duì)列尺寸是關(guān)鍵性要求,你應(yīng)該避免這類爆發(fā)性,例如,通過在許多RTC步驟上分散多個事件的產(chǎn)生。
簡單的規(guī)則事件池的尺寸取決于你的事件隊(duì)列和活動對象的和,實(shí)際取決于活著的動態(tài)事件的數(shù)量,真實(shí)的情況要比這復(fù)雜,只有在實(shí)戰(zhàn)中慢慢理解。關(guān)于內(nèi)存管理的討論到這里就結(jié)束啦,這一篇站在應(yīng)用角度上雖然少圖少代碼,但確實(shí)最重要,內(nèi)功心法太難配圖,先大體有個了解,當(dāng)在實(shí)際應(yīng)用時慢慢體會這些理論。