實時系統(tǒng)概念_第1頁
實時系統(tǒng)概念_第2頁
實時系統(tǒng)概念_第3頁
實時系統(tǒng)概念_第4頁
實時系統(tǒng)概念_第5頁
已閱讀5頁,還剩35頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、I第第 2 章章實時系統(tǒng)概念實時系統(tǒng)概念.12.0前后臺系統(tǒng) (FOREGROUND/BACKGROUND SYSTEM).12.1代碼的臨界段.22.2資源.22.3共享資源.22.4多任務(wù).22.5任務(wù).22.6任務(wù)切換(CONTEXT SWITCH OR TASK SWITCH).32.7內(nèi)核(KERNEL) .32.8調(diào)度(SCHEDULER).42.9不可剝奪型內(nèi)核 (NON-PREEMPTIVE KERNEL) .42.10可剝奪型內(nèi)核.52.11可重入性(REENTRANCY).52.12時間片輪番調(diào)度法.72.13任務(wù)優(yōu)先級.72.142.14 靜態(tài)優(yōu)先級.72.15動態(tài)優(yōu)先級

2、.72.16優(yōu)先級反轉(zhuǎn).72.17任務(wù)優(yōu)先級分配.82.18互斥條件.10關(guān)中斷和開中斷.10測試并置位.11禁止,然后允許任務(wù)切換.11信號量(Semaphores).122.19死鎖(或抱死)(DEADLOCK (OR DEADLY EMBRACE)).162.20同步.162.21事件標(biāo)志(EVENT FLAGS).182.22任務(wù)間的通訊(INTERTASK COMMUNICATION).182.23消息郵箱(MESSAGE MAIL BOXES).182.24消息隊列(MESSAGE QUEUE).192.25中斷.202.26中斷延遲.202.27中斷響應(yīng).212.28中斷恢復(fù)時間

3、(INTERRUPT RECOVERY).212.29中斷延遲、響應(yīng)和恢復(fù).222.30中斷處理時間.222.31非屏蔽中斷(NMI).232.32時鐘節(jié)拍(CLOCK TICK).24II2.33對存儲器的需求.252.34使用實時內(nèi)核的優(yōu)缺點.262.35實時系統(tǒng)小結(jié).261第第 2 章章 實時系統(tǒng)概念實時系統(tǒng)概念實時系統(tǒng)的特點是,如果邏輯和時序出現(xiàn)偏差將會引起嚴(yán)重后果的系統(tǒng)。有兩種類型的實時系統(tǒng):軟實時系統(tǒng)和硬實時系統(tǒng)。在軟實時系統(tǒng)中系統(tǒng)的宗旨是使各個任務(wù)運行得越快越好,并不要求限定某一任務(wù)必須在多長時間內(nèi)完成。在硬實時系統(tǒng)中,各任務(wù)不僅要執(zhí)行無誤而且要做到準(zhǔn)時。大多數(shù)實時系統(tǒng)是二者的結(jié)

4、合。實時系統(tǒng)的應(yīng)用涵蓋廣泛的領(lǐng)域,而多數(shù)實時系統(tǒng)又是嵌入式的。這意味著計算機建在系統(tǒng)內(nèi)部,用戶看不到有個計算機在系統(tǒng)里面。以下是一些嵌入式系統(tǒng)的例子:實時應(yīng)用軟件的設(shè)計一般比非實時應(yīng)用軟件設(shè)計難一些。本章講述實時系統(tǒng)概念。2.0前后臺系統(tǒng)前后臺系統(tǒng)(Foreground/Background System)不復(fù)雜的小系統(tǒng)一般設(shè)計成如圖 2.1 所示的樣子。這種系統(tǒng)可稱為前后臺系統(tǒng)或超循環(huán)系統(tǒng)(Super-Loops)。應(yīng)用程序是一個無限的循環(huán),循環(huán)中調(diào)用相應(yīng)的函數(shù)完成相應(yīng)的操作,這部分可以看成后臺行為(background)。中斷服務(wù)程序處理異步事件,這部分可以看成前臺行為(foregroun

5、d) 。后臺也可以叫做任務(wù)級。前臺也叫中斷級。時間相關(guān)性很強的關(guān)鍵操作(Critical operation)一定是靠中斷服務(wù)來保證的。因為中斷服務(wù)提供的信息一直要等到后臺程序走到該處理這個信息這一步時才能得到處理,這種系統(tǒng)在處理信息的及時性上,比實際可以做到的要差。這個指標(biāo)稱作任務(wù)級響應(yīng)時間。最壞情況下的任務(wù)級響應(yīng)時間取決于整個循環(huán)的執(zhí)行時間。因為循環(huán)的執(zhí)行時間不是常數(shù),程序經(jīng)過某一特定部分的準(zhǔn)確時間也是不能確定的。進(jìn)而,如果程序修改了,循環(huán)的時序也會受到影響。過程控制食品加工化工廠汽車業(yè)發(fā)動機控制防抱死系統(tǒng)(ABS)辦公自動化傳真機復(fù)印機計算機外設(shè)打印機計算機終端掃描儀調(diào)制解調(diào)器通訊類Sw

6、itch Hurb路由器機器人航空航天飛機管理系統(tǒng)武器系統(tǒng)噴氣發(fā)動機控制民用消費品微波爐洗碗機洗依機穩(wěn)溫調(diào)節(jié)器2圖 2-1 前后臺系統(tǒng) 很多基于微處理器的產(chǎn)品采用前后臺系統(tǒng)設(shè)計,例如微波爐、電話機、玩具等。在另外一些基于微處理器的應(yīng)用中,從省電的角度出發(fā),平時微處理器處在停機狀態(tài)(halt),所有的事都靠中斷服務(wù)來完成。2.1代碼的臨界段代碼的臨界段代碼的臨界段也稱為臨界區(qū),指處理時不可分割的代碼。一旦這部分代碼開始執(zhí)行,則不允許任何中斷打入。為確保臨界段代碼的執(zhí)行,在進(jìn)入臨界段之前要關(guān)中斷,而臨界段代碼執(zhí)行完以后要立即開中斷。(參閱 2.03 共享資源)2.2 資源資源任何為任務(wù)所占用的實體

7、都可稱為資源。資源可以是輸入輸出設(shè)備,例如打印機、鍵盤、顯示器,資源也可以是一個變量,一個結(jié)構(gòu)或一個數(shù)組等。2.3共享資源共享資源可以被一個以上任務(wù)使用的資源叫做共享資源。為了防止數(shù)據(jù)被破壞,每個任務(wù)在與共享資源打交道時,必須獨占該資源。這叫做互斥(mutual exclusion) 。在 2.18 節(jié)“互斥”中,將對技術(shù)上如何保證互斥條件做進(jìn)一步討論。2.4多任務(wù)多任務(wù)多任務(wù)運行的實現(xiàn)實際上是靠 CPU(中央處理單元)在許多任務(wù)之間轉(zhuǎn)換、調(diào)度。CPU3只有一個,輪番服務(wù)于一系列任務(wù)中的某一個。多任務(wù)運行很像前后臺系統(tǒng),但后臺任務(wù)有多個。多任務(wù)運行使 CPU 的利用率得到最大的發(fā)揮,并使應(yīng)用程

8、序模塊化。在實時應(yīng)用中,多任務(wù)化的最大特點是,開發(fā)人員可以將很復(fù)雜的應(yīng)用程序?qū)哟位J褂枚嗳蝿?wù),應(yīng)用程序?qū)⒏菀自O(shè)計與維護(hù)。2.5任務(wù)任務(wù)一個任務(wù),也稱作一個線程,是一個簡單的程序,該程序可以認(rèn)為 CPU 完全只屬該程序自己。實時應(yīng)用程序的設(shè)計過程,包括如何把問題分割成多個任務(wù),每個任務(wù)都是整個應(yīng)用的某一部分,每個任務(wù)被賦予一定的優(yōu)先級,有它自己的一套 CPU 寄存器和自己的??臻g(如圖 2.2 所示)。圖 2.2 多任務(wù)。4典型地、每個任務(wù)都是一個無限的循環(huán)。每個任務(wù)都處在以下 5 種狀態(tài)之一的狀態(tài)下,這 5 種狀態(tài)是休眠態(tài),就緒態(tài)、運行態(tài)、掛起態(tài)(等待某一事件發(fā)生)和被中斷態(tài)(參見圖2.3

9、) 休眠態(tài)相當(dāng)于該任務(wù)駐留在內(nèi)存中,但并不被多任務(wù)內(nèi)核所調(diào)度。就緒意味著該任務(wù)已經(jīng)準(zhǔn)備好,可以運行了,但由于該任務(wù)的優(yōu)先級比正在運行的任務(wù)的優(yōu)先級低,還暫時不能運行。運行態(tài)的任務(wù)是指該任務(wù)掌握了 CPU 的控制權(quán),正在運行中。掛起狀態(tài)也可以叫做等待事件態(tài) WAITING,指該任務(wù)在等待,等待某一事件的發(fā)生, (例如等待某外設(shè)的 I/O 操作,等待某共享資源由暫不能使用變成能使用狀態(tài),等待定時脈沖的到來或等待超時信號的到來以結(jié)束目前的等待,等等) 。最后,發(fā)生中斷時,CPU 提供相應(yīng)的中斷服務(wù),原來正在運行的任務(wù)暫不能運行,就進(jìn)入了被中斷狀態(tài)。圖 2.3 表示C/OS-中一些函數(shù)提供的服務(wù),這些

10、函數(shù)使任務(wù)從一種狀態(tài)變到另一種狀態(tài)。圖 2.3 任務(wù)的狀態(tài)2.6任務(wù)切換任務(wù)切換(Context(Context SwitchSwitch oror TaskTask Switch)Switch)Context Switch 在有的書中翻譯成上下文切換,實際含義是任務(wù)切換,或 CPU 寄存器內(nèi)容切換。當(dāng)多任務(wù)內(nèi)核決定運行另外的任務(wù)時,它保存正在運行任務(wù)的當(dāng)前狀態(tài)(Context) ,即 CPU 寄存器中的全部內(nèi)容。這些內(nèi)容保存在任務(wù)的當(dāng)前狀況保存區(qū)(Tasks Context Storage area) ,也就是任務(wù)自己的棧區(qū)之中。 (見圖 2.2) 。入棧工作完成以后,就是把下一個將要運行的

11、任務(wù)的當(dāng)前狀況從該任務(wù)的棧中重新裝入 CPU 的寄存器,并開始下一個任務(wù)的運行。這個過程叫做任務(wù)切換。任務(wù)切換過程增加了應(yīng)用程序的額外負(fù)荷。CPU 的內(nèi)部寄存器越多,額外負(fù)荷就越重。做任務(wù)切換所需要的時間取決于 CPU 有多少寄存器要入棧。實時內(nèi)核的性能不應(yīng)該以每秒鐘能做多少次任務(wù)切換來評價。52.7內(nèi)核(內(nèi)核(KernelKernel)多任務(wù)系統(tǒng)中,內(nèi)核負(fù)責(zé)管理各個任務(wù),或者說為每個任務(wù)分配 CPU 時間,并且負(fù)責(zé)任務(wù)之間的通訊。內(nèi)核提供的基本服務(wù)是任務(wù)切換。之所以使用實時內(nèi)核可以大大簡化應(yīng)用系統(tǒng)的設(shè)計,是因為實時內(nèi)核允許將應(yīng)用分成若干個任務(wù),由實時內(nèi)核來管理它們。內(nèi)核本身也增加了應(yīng)用程序的

12、額外負(fù)荷,代碼空間增加 ROM 的用量,內(nèi)核本身的數(shù)據(jù)結(jié)構(gòu)增加了 RAM 的用量。但更主要的是,每個任務(wù)要有自己的??臻g,這一塊吃起內(nèi)存來是相當(dāng)厲害的。內(nèi)核本身對 CPU 的占用時間一般在 2 到 5 個百分點之間。單片機一般不能運行實時內(nèi)核,因為單片機的 RAM 很有限。通過提供必不可缺少 的系統(tǒng)服務(wù),諸如信號量管理,郵箱、消息隊列、延時等,實時內(nèi)核使得 CPU 的利用更為有效。一旦讀者用實時內(nèi)核做過系統(tǒng)設(shè)計,將決不再想返回到前后臺系統(tǒng)。2.8調(diào)度調(diào)度(Scheduler)調(diào)度(Scheduler),英文還有一詞叫 dispatcher,也是調(diào)度的意思。這是內(nèi)核的主要職責(zé)之一,就是要決定該輪

13、到哪個任務(wù)運行了。多數(shù)實時內(nèi)核是基于優(yōu)先級調(diào)度法的。每個任務(wù)根據(jù)其重要程度的不同被賦予一定的優(yōu)先級。基于優(yōu)先級的調(diào)度法指,CPU 總是讓處在就緒態(tài)的優(yōu)先級最高的任務(wù)先運行。然而,究竟何時讓高優(yōu)先級任務(wù)掌握 CPU 的使用權(quán),有兩種不同的情況,這要看用的是什么類型的內(nèi)核,是不可剝奪型的還是可剝奪型內(nèi)核。2.9不可剝奪型內(nèi)核不可剝奪型內(nèi)核 (Non-Preemptive Kernel)不可剝奪型內(nèi)核要求每個任務(wù)自我放棄 CPU 的所有權(quán)。不可剝奪型調(diào)度法也稱作合作型多任務(wù),各個任務(wù)彼此合作共享一個 CPU。異步事件還是由中斷服務(wù)來處理。中斷服務(wù)可以使一個高優(yōu)先級的任務(wù)由掛起狀態(tài)變?yōu)榫途w狀態(tài)。但中斷

14、服務(wù)以后控制權(quán)還是回到原來被中斷了的那個任務(wù),直到該任務(wù)主動放棄 CPU 的使用權(quán)時,那個高優(yōu)先級的任務(wù)才能獲得 CPU 的使用權(quán)。不可剝奪型內(nèi)核的一個優(yōu)點是響應(yīng)中斷快。在討論中斷響應(yīng)時會進(jìn)一步涉及這個問題。在任務(wù)級,不可剝奪型內(nèi)核允許使用不可重入函數(shù)。函數(shù)的可重入性以后會討論。每個任務(wù)都可以調(diào)用非可重入性函數(shù),而不必?fù)?dān)心其它任務(wù)可能正在使用該函數(shù),從而造成數(shù)據(jù)的破壞。因為每個任務(wù)要運行到完成時才釋放 CPU 的控制權(quán)。當(dāng)然該不可重入型函數(shù)本身不得有放棄 CPU 控制權(quán)的企圖。使用不可剝奪型內(nèi)核時,任務(wù)級響應(yīng)時間比前后臺系統(tǒng)快得多。此時的任務(wù)級響應(yīng)時間取決于最長的任務(wù)執(zhí)行時間。不可剝奪型內(nèi)核的

15、另一個優(yōu)點是,幾乎不需要使用信號量保護(hù)共享數(shù)據(jù)。運行著的任務(wù)占有 CPU,而不必?fù)?dān)心被別的任務(wù)搶占。但這也不是絕對的,在某種情況下,信號量還是用得著的。處理共享 I/O 設(shè)備時仍需要使用互斥型信號量。例如,在打印機的使用上,6仍需要滿足互斥條件。圖 2.4 示意不可剝奪型內(nèi)核的運行情況,任務(wù)在運行過程之中,L2.4(1)中斷來了,如果此時中斷是開著的,CPU 由中斷向量F2.4(2)進(jìn)入中斷服務(wù)子程序,中斷服務(wù)子程序做事件處理F2.4(3),使一個有更高級的任務(wù)進(jìn)入就緒態(tài)。中斷服務(wù)完成以后,中斷返回指令F2.4(4), 使 CPU 回到原來被中斷的任務(wù),接著執(zhí)行該任務(wù)的代碼F2.4(5)直到該

16、任務(wù)完成,調(diào)用一個內(nèi)核服務(wù)函數(shù)以釋放 CPU 控制權(quán),由內(nèi)核將控制權(quán)交給那個優(yōu)先級更高的、并已進(jìn)入就緒態(tài)的任務(wù)F2.4(6),這個優(yōu)先級更高的任務(wù)才開始處理中斷服務(wù)程序標(biāo)識的事件F2.4(7)。 圖 2.4 不可剝奪型內(nèi)核不可剝奪型內(nèi)核的最大缺陷在于其響應(yīng)時間。高優(yōu)先級的任務(wù)已經(jīng)進(jìn)入就緒態(tài),但還不能運行,要等,也許要等很長時間,直到當(dāng)前運行著的任務(wù)釋放 CPU。與前后系統(tǒng)一樣,不可剝奪型內(nèi)核的任務(wù)級響應(yīng)時間是不確定的,不知道什么時候最高優(yōu)先級的任務(wù)才能拿到 CPU 的控制權(quán),完全取決于應(yīng)用程序什么時候釋放 CPU??傊?,不可剝奪型內(nèi)核允許每個任務(wù)運行,直到該任務(wù)自愿放棄 CPU 的控制權(quán)。中斷

17、可以打入運行著的任務(wù)。中斷服務(wù)完成以后將 CPU 控制權(quán)還給被中斷了的任務(wù)。任務(wù)級響應(yīng)時間要大大好于前后系統(tǒng),但仍是不可知的,商業(yè)軟件幾乎沒有不可剝奪型內(nèi)核。2.10可可剝奪型內(nèi)核剝奪型內(nèi)核當(dāng)系統(tǒng)響應(yīng)時間很重要時,要使用可剝奪型內(nèi)核。因此,C/OS-以及絕大多數(shù)商業(yè)上銷售的實時內(nèi)核都是可剝奪型內(nèi)核。最高優(yōu)先級的任務(wù)一旦就緒,總能得到 CPU 的控制權(quán)。當(dāng)一個運行著的任務(wù)使一個比它優(yōu)先級高的任務(wù)進(jìn)入了就緒態(tài),當(dāng)前任務(wù)的 CPU 使用7權(quán)就被剝奪了,或者說被掛起了,那個高優(yōu)先級的任務(wù)立刻得到了 CPU 的控制權(quán)。如果是中斷服務(wù)子程序使一個高優(yōu)先級的任務(wù)進(jìn)入就緒態(tài),中斷完成時,中斷了的任務(wù)被掛起,優(yōu)

18、先級高的那個任務(wù)開始運行。如圖 2.5 所示。圖 2.5 可剝奪型內(nèi)核使用可剝奪型內(nèi)核,最高優(yōu)先級的任務(wù)什么時候可以執(zhí)行,可以得到 CPU 的控制權(quán)是可知的。使用可剝奪型內(nèi)核使得任務(wù)級響應(yīng)時間得以最優(yōu)化。使用可剝奪型內(nèi)核時,應(yīng)用程序不應(yīng)直接使用不可重入型函數(shù)。調(diào)用不可重入型函數(shù)時,要滿足互斥條件,這一點可以用互斥型信號量來實現(xiàn)。如果調(diào)用不可重入型函數(shù)時,低優(yōu)先級的任務(wù) CPU 的使用權(quán)被高優(yōu)先級任務(wù)剝奪,不可重入型函數(shù)中的數(shù)據(jù)有可能被破壞。綜上所述,可剝奪型內(nèi)核總是讓就緒態(tài)的高優(yōu)先級的任務(wù)先運行,中斷服務(wù)程序可以搶占 CPU,到中斷服務(wù)完成時,內(nèi)核讓此時優(yōu)先級最高的任務(wù)運行(不一定是那個被中斷

19、了的任務(wù)) 。任務(wù)級系統(tǒng)響應(yīng)時間得到了最優(yōu)化,且是可知的。C/OS-屬于可剝奪型內(nèi)核。2.11 可重入可重入性(性(Reentrancy)可重入型函數(shù)可以被一個以上的任務(wù)調(diào)用,而不必?fù)?dān)心數(shù)據(jù)的破壞。可重入型函數(shù)任何時候都可以被中斷,一段時間以后又可以運行,而相應(yīng)數(shù)據(jù)不會丟失。可重入型函數(shù)或者只使用局部變量,即變量保存在 CPU 寄存器中或堆棧中。如果使用全局變量,則要對全局變量予以保護(hù)。程序 2.1 是一個可重入型函數(shù)的例子。程序清單程序清單2.1可重入型函數(shù)可重入型函數(shù)void strcpy(char *dest, char *src)8 while (*dest+ = *src+) ; *

20、dest = NUL;函數(shù) Strcpy()做字符串復(fù)制。因為參數(shù)是存在堆棧中的,故函數(shù) Strcpy()可以被多個任務(wù)調(diào)用,而不必?fù)?dān)心各任務(wù)調(diào)用函數(shù)期間會互相破壞對方的指針。不可重入型函數(shù)的例子如程序 2.2 所示。Swap()是一個簡單函數(shù),它使函數(shù)的兩個形式變量的值互換。為便于討論,假定使用的是可剝奪型內(nèi)核,中斷是開著的,Temp 定義為整數(shù)全程變量。 程序清單程序清單 2.22.2 不可重入型函數(shù)不可重入型函數(shù)int Temp;void swap(int *x, int *y) Temp = *x; *x = *y; *y = Temp;程序員打算讓 Swap() 函數(shù)可以為任何任務(wù)所

21、調(diào)用,如果一個低優(yōu)先級的任務(wù)正在執(zhí)行 Swap()函數(shù),而此時中斷發(fā)生了,于是可能發(fā)生的事情如圖 2.6 所示。F2.6(1)表示中斷發(fā)生時 Temp 已被賦值 1,中斷服務(wù)子程序使更優(yōu)先級的任務(wù)就緒,當(dāng)中斷完成時F2.6(2),內(nèi)核(假定使用的是 C/OS-)使高優(yōu)先級的那個任務(wù)得以運行F2.6(3),高優(yōu)先級的任務(wù)調(diào)用 Swap()函數(shù)是 Temp 賦值為 3。這對該任務(wù)本身來說,實現(xiàn)兩個變量的交換是沒有問題的,交換后 Z 的值是 4,X 的值是 3。然后高優(yōu)先級的任務(wù)通過調(diào)用內(nèi)核服務(wù)函數(shù)中的延遲一個時鐘節(jié)拍F2.6(4),釋放了 CPU 的使用權(quán),低優(yōu)先級任務(wù)得以繼續(xù)運行F2.6(5).

22、注意,此時 Temp 的值仍為 3!在低優(yōu)先級任務(wù)接著運行時,Y 的值被錯誤地賦為 3,而不是正確值 1。9圖 2.6 不可重入性函數(shù)請注意,這只是一個簡單的例子,如何能使代碼具有可重入性一看就明白。然而有些情況下,問題并非那么易解。應(yīng)用程序中的不可重入函數(shù)引起的錯誤很可能在測試時發(fā)現(xiàn)不了,直到產(chǎn)品到了現(xiàn)場問題才出現(xiàn)。如果在多任務(wù)上您還是把新手,使用不可重入型函數(shù)時,千萬要當(dāng)心。使用以下技術(shù)之一即可使 Swap()函數(shù)具有可重入性:把 Temp 定義為局部變量調(diào)用 Swap()函數(shù)之前關(guān)中斷,調(diào)動后再開中斷用信號量禁止該函數(shù)在使用過程中被再次調(diào)用如果中斷發(fā)生在 Swap()函數(shù)調(diào)用之前或調(diào)用之

23、后,兩個任務(wù)中的 X,Y 值都會是正確的。2.12 時間片輪番調(diào)度法時間片輪番調(diào)度法當(dāng)兩個或兩個以上任務(wù)有同樣優(yōu)先級,內(nèi)核允許一個任務(wù)運行事先確定的一段時間,叫做時間額度(quantum),然后切換給另一個任務(wù)。也叫做時間片調(diào)度。內(nèi)核在滿足以下條件時,把 CPU 控制權(quán)交給下一個任務(wù)就緒態(tài)的任務(wù):當(dāng)前任務(wù)已無事可做當(dāng)前任務(wù)在時間片還沒結(jié)束時已經(jīng)完成了。目前,C/OS-不支持時間片輪番調(diào)度法。應(yīng)用程序中各任務(wù)的優(yōu)先級必須互不相同。102.13 任務(wù)優(yōu)先級任務(wù)優(yōu)先級每個任務(wù)都有其優(yōu)先級。任務(wù)越重要,賦予的優(yōu)先級應(yīng)越高。2.14 2.142.14 靜態(tài)優(yōu)先級靜態(tài)優(yōu)先級應(yīng)用程序執(zhí)行過程中諸任務(wù)優(yōu)先級不

24、變,則稱之為靜態(tài)優(yōu)先級。在靜態(tài)優(yōu)先級系統(tǒng)中,諸任務(wù)以及它們的時間約束在程序編譯時是已知的。2.15 動態(tài)優(yōu)先級動態(tài)優(yōu)先級應(yīng)用程序執(zhí)行過程中,任務(wù)的優(yōu)先級是可變的,則稱之為動態(tài)優(yōu)先級。實時內(nèi)核應(yīng)當(dāng)避免出現(xiàn)優(yōu)先級反轉(zhuǎn)問題。2.16 優(yōu)先級反轉(zhuǎn)優(yōu)先級反轉(zhuǎn)使用實時內(nèi)核,優(yōu)先級反轉(zhuǎn)問題是實時系統(tǒng)中出現(xiàn)得最多的問題。圖 2.7 解釋優(yōu)先級反轉(zhuǎn)是如何出現(xiàn)的。如圖,任務(wù) 1 優(yōu)先級高于任務(wù) 2,任務(wù) 2 優(yōu)先級高于任務(wù) 3。任務(wù) 1 和任務(wù) 2 處于掛起狀態(tài),等待某一事件的發(fā)生,任務(wù) 3 正在運行如圖 2.7(1)。此時,任務(wù) 3要使用其共享資源。使用共享資源之前,首先必須得到該資源的信號量(Semaphor

25、e)(見 2. 18.04 信號量)。任務(wù) 3 得到了該信號量,并開始使用該共享資源圖 2.7(2)。由于任務(wù)1 優(yōu)先級高,它等待的事件到來之后剝奪了任務(wù) 3 的 CPU 使用權(quán)圖 2.7(3),任務(wù) 1 開始運行圖 2.7(4)。運行過程中任務(wù) 1 也要使用那個任務(wù) 3 正在使用著的資源,由于該資源的信號量還被任務(wù) 3 占用著,任務(wù) 1 只能進(jìn)入掛起狀態(tài),等待任務(wù) 3 釋放該信號量圖2.7(5)。任務(wù) 3 得以繼續(xù)運行圖 2.7(6)。由于任務(wù) 2 的優(yōu)先級高于任務(wù) 3,當(dāng)任務(wù) 2 等待的事件發(fā)生后,任務(wù) 2 剝奪了任務(wù) 3 的 CPU 的使用權(quán)圖 2.7(7)并開始運行。處理它該處理的事件

26、圖 2.7(8),直到處理完之后將 CPU 控制權(quán)還給任 3圖 2.7(9)。任務(wù) 3 接著運行圖 2.7(10),直到釋放那個共享資源的信號量圖 27(11)。直到此時,由于實時內(nèi)核知道有個高優(yōu)先級的任務(wù)在等待這個信號量,內(nèi)核做任務(wù)切換,使任務(wù) 1 得到該信號量并接著運行圖 2.7(12)。在這種情況下,任務(wù) 1 優(yōu)先級實際上降到了任務(wù) 3 的優(yōu)先級水平。因為任務(wù) 1 要等,直等到任務(wù) 3 釋放占有的那個共享資源。由于任務(wù) 2 剝奪任務(wù) 3 的 CPU 使用權(quán),使任務(wù) 1 的狀況更加惡化,任務(wù) 2 使任務(wù) 1 增加了額外的延遲時間。任務(wù) 1 和任務(wù) 2 的優(yōu)先級發(fā)生了反轉(zhuǎn)。糾正的方法可以是,

27、在任務(wù) 3 使用共享資源時,提升任務(wù) 3 的優(yōu)先級。任務(wù)完成時予以恢復(fù)。任務(wù) 3 的優(yōu)先級必須升至最高,高于允許使用該資源的任何任務(wù)。多任務(wù)內(nèi)核應(yīng)允許動態(tài)改變?nèi)蝿?wù)的優(yōu)先級以避免發(fā)生優(yōu)先級反轉(zhuǎn)現(xiàn)象。然而改變?nèi)蝿?wù)的優(yōu)先級是很花時間的。如果任務(wù) 3 并沒有先被任務(wù) 1 剝奪 CPU 使用權(quán),又被任務(wù) 2 搶走了 CPU 使用權(quán),花很多時間11在共享資源使用前提升任務(wù) 3 的優(yōu)先級,然后又在資源使用后花時間恢復(fù)任務(wù) 3 的優(yōu)先級,則無形中浪費了很多 CPU 時間。真正需要的是,為防止發(fā)生優(yōu)先級反轉(zhuǎn),內(nèi)核能自動變換任務(wù)的優(yōu)先級,這叫做優(yōu)先級繼承(Priority inheritance)但 C/OS-不

28、支持優(yōu)先級繼承,一些商業(yè)內(nèi)核有優(yōu)先級繼承功能。圖 2.7優(yōu)先級反轉(zhuǎn)問題圖 2.8 解釋如果內(nèi)核支持優(yōu)先級繼承的話,在上述例子中會是怎樣一個過程。任務(wù) 3 在運行圖 2.8(1),任務(wù) 3 申請信號量以獲得共享資源使用權(quán)圖 2.8(2),任務(wù) 3 得到并開始使用共享資源圖 2.8(3)。后來 CPU 使用權(quán)被任務(wù) 1 剝奪圖 2.8(4),任務(wù) 1 開始運行圖 2.8(5),任務(wù) 1 申請共享資源信號量圖 2.8(6)。此時,內(nèi)核知道該信號量被任務(wù) 3 占用了,而任務(wù) 3 的優(yōu)先級比任務(wù) 1 低,內(nèi)核于是將任務(wù) 3 的優(yōu)先級升至與任務(wù) 1 一樣,然而回到任務(wù) 3 繼續(xù)運行,使用該共享資源圖 2.

29、7(7),直到任務(wù) 3 釋放共享資源信號量圖2。8(8)。這時,內(nèi)核恢復(fù)任務(wù) 3 本來的優(yōu)先級并把信號量交給任務(wù) 1,任務(wù) 1 得以順利運行。 圖 2.8(9),任務(wù) 1 完成以后圖 2.8(10)那些任務(wù)優(yōu)先級在任務(wù) 1 與任務(wù) 3 之間的任務(wù)例如任務(wù) 2 才能得到 CPU 使用權(quán),并開始運行 圖 2.8(11)。注意,任務(wù) 2 在從圖2.8(3)到圖 2.8(10)的任何一刻都有可能進(jìn)入就緒態(tài),并不影響任務(wù) 1、任務(wù) 3 的完成過程。在某種程度上,任務(wù) 2 和任務(wù) 3 之間也還是有不可避免的優(yōu)先級反轉(zhuǎn)。12圖 2.82.17 任務(wù)優(yōu)先級任務(wù)優(yōu)先級分配分配給任務(wù)定優(yōu)先級可不是件小事,因為實時

30、系統(tǒng)相當(dāng)復(fù)雜。許多系統(tǒng)中,并非所有的任務(wù)都至關(guān)重要。不重要的任務(wù)自然優(yōu)先級可以低一些。實時系統(tǒng)大多綜合了軟實時和硬實時這兩種需求。軟實時系統(tǒng)只是要求任務(wù)執(zhí)行得盡量快,并不要求在某一特定時間內(nèi)完成。硬實時系統(tǒng)中,任務(wù)不但要執(zhí)行無誤,還要準(zhǔn)時完成。一項有意思的技術(shù)可稱之為單調(diào)執(zhí)行率調(diào)度法 RMS(Rate Monotonic Scheduling),用于分配任務(wù)優(yōu)先級。這種方法基于哪個任務(wù)執(zhí)行的次數(shù)最頻繁,執(zhí)行最頻繁的任務(wù)優(yōu)先級最高。見圖 2.9。圖 2.9 基于任務(wù)執(zhí)行頻繁度的優(yōu)先級分配法任務(wù)執(zhí)行頻繁度(Hz)RMS 做了一系列假設(shè):13) 12(/1ninTiEi)2(n所有任務(wù)都是周期性的任

31、務(wù)間不需要同步,沒有共享資源,沒有任務(wù)間數(shù)據(jù)交換等問題CPU 必須總是執(zhí)行那個優(yōu)先級最高且處于就緒態(tài)的任務(wù)。換句話說,要使用可剝奪型調(diào)度法。給出一系列 n 值表示系統(tǒng)中的不同任務(wù)數(shù),要使所有的任務(wù)滿足硬實時條件,必須使不等式2.1成立,這就是 RMS 定理:2.1 這里 Ei是任務(wù) i 最長執(zhí)行時間,Ti是任務(wù) i 的執(zhí)行周期。換句話說,Ei/Ti是任務(wù) i 所需的 CPU 時間。表 2.1 給出 n(21/n - 1 )的值,n 是系統(tǒng)中的任務(wù)數(shù)。對于無窮多個任務(wù),極限值是 或 0.693。這就意味著,基于 RMS,要任務(wù)都滿足硬實時條件,所有有時間條件要求的任務(wù) i 總的 CPU 利用時間

32、應(yīng)小于 70%!請注意,這是指有時間條件要求的任務(wù),系統(tǒng)中當(dāng)然還可以有對時間沒有什么要求的任務(wù),使得CPU 的利用率達(dá)到 100%。使 CPU 利用率達(dá)到 100%并不好,因為那樣的話程序就沒有了修改的余地,也沒法增加新功能了。作為系統(tǒng)設(shè)計的一條原則,CPU 利用率應(yīng)小于 60%到 70%。 RMS 認(rèn)為最高執(zhí)行率的任務(wù)具有最高的優(yōu)先級,但最某些情況下,最高執(zhí)行率的任務(wù)并非是最重要的任務(wù)。如果實際應(yīng)用都真的像 RMS 說的那樣,也就沒有什么優(yōu)先級分配可討論了。然而討論優(yōu)先級分配問題,RMS 無疑是一個有意思的起點。表表2.1基于任務(wù)到基于任務(wù)到CPU最高允許使用率最高允許使用率.任務(wù)數(shù)任務(wù)數(shù)n

33、 n(21/n n - 1)11.00020.82830.77940.75650.743.0.693142.18 互斥條件互斥條件實現(xiàn)任務(wù)間通訊最簡便到辦法是使用共享數(shù)據(jù)結(jié)構(gòu)。特別是當(dāng)所有到任務(wù)都在一個單一地址空間下,能使用全程變量、指針、緩沖區(qū)、鏈表、循環(huán)緩沖區(qū)等,使用共享數(shù)據(jù)結(jié)構(gòu)通訊就更為容易。雖然共享數(shù)據(jù)區(qū)法簡化了任務(wù)間的信息交換,但是必須保證每個任務(wù)在處理共享數(shù)據(jù)時的排它性,以避免競爭和數(shù)據(jù)的破壞。與共享資源打交道時,使之滿足互斥條件最一般的方法有:關(guān)中斷使用測試并置位指令禁止做任務(wù)切換利用信號量2.18.1關(guān)中斷和開中斷關(guān)中斷和開中斷處理共享數(shù)據(jù)時保證互斥,最簡便快捷的辦法是關(guān)中斷和

34、開中斷。如示意性代碼程序2.3 所示:程序清單程序清單2.3 關(guān)中斷和開中斷關(guān)中斷和開中斷Disable interrupts; /*關(guān)中斷*/Access the resource (read/write from/to variables); /*讀/寫變量*/Reenable interrupts; /*重新允許中斷*/ C/OS-在處理內(nèi)部變量和數(shù)據(jù)結(jié)構(gòu)時就是使用的這種手段,即使不是全部,也是絕大部分。實際上 C/OS-程序清單程序清單2.4利用利用 C/OS_ 宏調(diào)用關(guān)中斷和開中斷宏調(diào)用關(guān)中斷和開中斷void Function (void) OS_ENTER_CRITICAL();

35、. . /*在這里處理共享數(shù)據(jù)*/ . OS_EXIT_CRITICAL();可是,必須十分小心,關(guān)中斷的時間不能太長。因為它影響整個系統(tǒng)的中斷響應(yīng)時間,15即中斷延遲時間。當(dāng)改變或復(fù)制某幾個變量的值時,應(yīng)想到用這種方法來做。這也是在中斷服務(wù)子程序中處理共享變量或共享數(shù)據(jù)結(jié)構(gòu)的唯一方法。在任何情況下,關(guān)中斷的時間都要盡量短。如果使用某種實時內(nèi)核,一般地說,關(guān)中斷的最長時間不超過內(nèi)核本身的關(guān)中斷時間,就不會影響系統(tǒng)中斷延遲。當(dāng)然得知道內(nèi)核里中斷關(guān)了多久。凡好的實時內(nèi)核,廠商都提供這方面的數(shù)據(jù)。總而言之,要想出售實時內(nèi)核,時間特性最重要。2.18.2測試并置位測試并置位如果不使用實時內(nèi)核,當(dāng)兩個任

36、務(wù)共享一個資源時,一定要約定好,先測試某一全程變量,如果該變量是 0,允許該任務(wù)與共享資源打交道。為防止另一任務(wù)也要使用該資源,前者只要簡單地將全程變量置為 1,這通常稱作測試并置位(Test-And-Set),或稱作TAS。TAS 操作可能是微處理器的單獨一條不會被中斷的指令,或者是在程序中關(guān)中斷做TAS 操作再開中斷,如程序清單 2.5 所示。程序清單程序清單2.5 利用測試并置位處理共享資源利用測試并置位處理共享資源Disable interrupts; 關(guān)中斷if (Access Variable is 0) 如果資源不可用,標(biāo)志為0 Set variable to 1; 置資源不可用

37、,標(biāo)志為1 Reenable interrupts; 重開中斷 Access the resource; 處理該資源 Disable interrupts; 關(guān)中斷 Set the Access Variable back to 0; 清資源不可使用,標(biāo)志為0 Reenable interrupts; 重新開中斷 else 否則 Reenable interrupts; 開中斷/* You dont have access to the resource, try back later; */* 資源不可使用,以后再試; */有的微處理器有硬件的 TAS 指令(如 Motorola 68000

38、 系列,就有這條指令)2.18.3禁止禁止, ,然后允許任務(wù)切換然后允許任務(wù)切換如果任務(wù)不與中斷服務(wù)子程序共享變量或數(shù)據(jù)結(jié)構(gòu),可以使用禁止、然后允許任務(wù)切換。(參見 3.06 給任務(wù)切換上鎖和開鎖)。如程序清單 2.6 所示,以 C/OS-的使用為例,兩個或兩個以上的任務(wù)可以共享數(shù)據(jù)而不發(fā)生競爭。注意,此時雖然任務(wù)切換是禁止了,但中斷還是開著的。如果這時中斷來了,中斷服務(wù)子程序會在這一臨界區(qū)內(nèi)立即執(zhí)行。中斷服務(wù)子程序結(jié)束時,盡管有優(yōu)先級高的任務(wù)已經(jīng)進(jìn)入就緒態(tài),內(nèi)核還是返回到原來被中斷16了的任務(wù)。直到執(zhí)行完給任務(wù)切換開鎖函數(shù) OSSchedUnlock (),內(nèi)核再看有沒有優(yōu)先級更高的任務(wù)被中

39、斷服務(wù)子程序激活而進(jìn)入就緒態(tài),如果有,則做任務(wù)切換。雖然這種方法是可行的,但應(yīng)該盡量避免禁止任務(wù)切換之類操作,因為內(nèi)核最主要的功能就是做任務(wù)的調(diào)度與協(xié)調(diào)。禁止任務(wù)切換顯然與內(nèi)核的初衷相違。應(yīng)該使用下述方法。程序清單程序清單2.62.6 用給任務(wù)切換上鎖,然后開鎖的方法實現(xiàn)數(shù)據(jù)共享用給任務(wù)切換上鎖,然后開鎖的方法實現(xiàn)數(shù)據(jù)共享.void Function (void) OSSchedLock(); . . /* You can access shared data in here (interrupts are recognized) */. /*在這里處理共享數(shù)據(jù)(中斷是開著的)*/ OSSch

40、edUnlock();2.18.4信號量信號量(Semaphores)(Semaphores)信號量是 60 年代中期 Edgser Dijkstra 發(fā)明的。信號量實際上是一種約定機制,在多任務(wù)內(nèi)核中普遍使用.信號量用于:控制共享資源的使用權(quán)(滿足互斥條件)標(biāo)志某事件的發(fā)生使兩個任務(wù)的行為同步(譯者注:信號與信號量在英文中都叫做 Semaphore,并不加以區(qū)分,而說它有兩種類型,二進(jìn)制型(binary)和計數(shù)器型(counting)。本書中的二進(jìn)制型信號量實際上是只取兩個值 0 和 1 的信號量。實際上 這個信號量只有一位,這種信號量翻譯為信號更為貼切。而二進(jìn)制信號量通常指若干位的組合。而

41、本書中解釋為事件標(biāo)志的置位與清除(見 2.21)。信號像是一把鑰匙,任務(wù)要運行下去,得先拿到這把鑰匙。如果信號已被別的任務(wù)占用,該任務(wù)只得被掛起,直到信號被當(dāng)前使用者釋放。換句話說,申請信號的任務(wù)是在說:“把鑰匙給我,如果誰正在用著,我只好等!”信號是只有兩個值的變量,信號量是計數(shù)式的。只取兩個值的信號是只有兩個值 0 和 1 的量,因此也稱之為信號量。計數(shù)式信號量的值可以是 0 到 255 或 0 到 65535,或 0 到 4294967295,取決于信號量規(guī)約機制使用的是8 位、16 位還是 32 位。到底是幾位,實際上是取決于用的哪種內(nèi)核。根據(jù)信號量的值,內(nèi)核跟蹤那些等待信號量的任務(wù)。

42、一般地說,對信號量只能實施三種操作:初始化(INITIALIZE),也可稱作建立(CREATE);等信號(WAIT)也可稱作掛起(PEND);給信號(SIGNAL)或發(fā)信號(POST)。信號量初始化時要17給信號量賦初值,等待信號量的任務(wù)表(Waiting list)應(yīng)清為空。想要得到信號量的任務(wù)執(zhí)行等待(WAIT)操作。如果該信號量有效(即信號量值大于 0),則信號量值減 1,任務(wù)得以繼續(xù)運行。如果信號量的值為 0,等待信號量的任務(wù)就被列入等待信號量任務(wù)表。多數(shù)內(nèi)核允許用戶定義等待超時,如果等待時間超過了某一設(shè)定值時,該信號量還是無效,則等待信號量的任務(wù)進(jìn)入就緒態(tài)準(zhǔn)備運行,并返回出錯代碼(指

43、出發(fā)生了等待超時錯誤)。任務(wù)以發(fā)信號操作(SIGNAL)釋放信號量。如果沒有任務(wù)在等待信號量,信號量的值僅僅是簡單地加 1。如果有任務(wù)在等待該信號量,那么就會有一個任務(wù)進(jìn)入就緒態(tài),信號量的值也就不加 1。于是鑰匙給了等待信號量的諸任務(wù)中的一個任務(wù)。至于給了那個任務(wù),要看內(nèi)核是如何調(diào)度的。收到信號量的任務(wù)可能是以下兩者之一。等待信號量任務(wù)中優(yōu)先級最高的,或者是最早開始等待信號量的那個任務(wù),即按先進(jìn)先出的原則(First In First Out ,F(xiàn)IFO)有的內(nèi)核有選擇項,允許用戶在信號量初始化時選定上述兩種方法中的一種。但C/OS-只支持優(yōu)先級法。如果進(jìn)入就緒態(tài)的任務(wù)比當(dāng)前運行的任務(wù)優(yōu)先級高

44、(假設(shè),是當(dāng)前任務(wù)釋放的信號量激活了比自己優(yōu)先級高的任務(wù))。則內(nèi)核做任務(wù)切換(假設(shè),使用的是可剝奪型內(nèi)核),高優(yōu)先級的任務(wù)開始運行。當(dāng)前任務(wù)被掛起。直到又變成就緒態(tài)中優(yōu)先級最高任務(wù)。程序清單 2.7 示意在 C/OS-中如何用信號量處理共享數(shù)據(jù)。要與同一共享數(shù)據(jù)打交道的任務(wù)調(diào)用等待信號量函數(shù) OSSemPend()。處理完共享數(shù)據(jù)以后再調(diào)用釋放信號量函數(shù) OSSemPost()。這兩個函數(shù)將在以后的章節(jié)中描述。要注意的是,在使用信號量之前,一定要對該信號量做初始化。作為互斥條件,信號量初始化為 1。使用信號量處理共享數(shù)據(jù)不增加中斷延遲時間,如果中斷服務(wù)程序或當(dāng)前任務(wù)激活了一個高優(yōu)先級的任務(wù),高

45、優(yōu)先級的任務(wù)立即開始執(zhí)行。程序清單程序清單2.7 通過獲得信號量處理共享數(shù)據(jù)通過獲得信號量處理共享數(shù)據(jù)OS_EVENT *SharedDataSem;void Function (void) INT8U err; OSSemPend(SharedDataSem, 0, &err); . . /* You can access shared data in here (interrupts are recognized) */ . /*共享數(shù)據(jù)的處理在此進(jìn)行,(中斷是開著的)*/ OSSemPost(SharedDataSem);18當(dāng)諸任務(wù)共享輸入輸出設(shè)備時,信號量特別有用??梢韵胂螅?/p>

46、如果允許兩個任務(wù)同時給打印機送數(shù)據(jù)時會出現(xiàn)什么現(xiàn)象。打印機會打出相互交叉的兩個任務(wù)的數(shù)據(jù)。例如任務(wù)1 要打印“I am Task!”,而任務(wù) 2 要打印“I am Task2!”可能打印出來的結(jié)果是:“I Ia amm T Tasask k1!2!”在這種情況下,使用信號量并給信號量賦初值 1(用二進(jìn)制信號量)。規(guī)則很簡單,要想使用打印機的任務(wù),先要得到該資源的信號量。圖 2.10 兩個任務(wù)競爭得到排它性打印機使用權(quán),圖中信號量用一把鑰匙表示,想使用打印機先要得到這把鑰匙。圖 2.10 用獲取信號量來得到打印機使用權(quán)上例中,每個任務(wù)都知道有個信號表示資源可不可以使用。要想使用該資源,要先得到這

47、個信號。然而有些情況下,最好把信號量藏起來,各個任務(wù)在同某一資源打交道時,并不知道實際上是在申請得到一個信號量。例如,多任務(wù)共享一個 RS-232C 外設(shè)接口,各任務(wù)要送命令給接口另一端的設(shè)備并接收該設(shè)備的回應(yīng)。如圖 2.11 所示。調(diào)用向串行口發(fā)送命令的函數(shù) CommSendCmd(),該函數(shù)有三個形式參數(shù):Cmd 指向送出的 ASCII 碼字符串命令。Response 指向外設(shè)回應(yīng)的字符串。timeout 指設(shè)定的時間間隔。如果超過這段時間外設(shè)還不響應(yīng),則返回超時錯誤信息。函數(shù)的示意代碼如程序清單 2.8所示。程序清單程序清單 2.82.8 隱含的信號量。隱含的信號量。INT8U Comm

48、SendCmd(char *cmd, char *response, INT16U timeout) Acquire ports semaphore; Send command to device; Wait for response (with timeout); if (timed out) 19 Release semaphore; return (error code); else Release semaphore; return (no error); 要向外設(shè)發(fā)送命令的任務(wù)得調(diào)用上述函數(shù)。設(shè)信號量初值為 1,表示允許使用。初始化是在通訊口驅(qū)動程序的初始化部分完成的。第一個調(diào)用 C

49、ommSendCmd()函數(shù)的任務(wù)申請并得到了信號量,開始向外設(shè)發(fā)送命令并等待響應(yīng)。而另一個任務(wù)也要送命令,此時外設(shè)正“忙” ,則第二個任務(wù)被掛起,直到該信號量重新被釋放。第二個任務(wù)看起來同調(diào)用了一個普通函數(shù)一樣,只不過這個函數(shù)在沒有完成其相應(yīng)功能時不返回。當(dāng)?shù)谝粋€任務(wù)釋放了那個信號量,第二個任務(wù)得到了該信號量,第二個任務(wù)才能使用 RS-232 口。圖 2.11 在任務(wù)級看不到隱含的信號量計數(shù)式信號量用于某資源可以同時為幾個任務(wù)所用。例如,用信號量管理緩沖區(qū)陣列(buffer pool),如圖 2.12 所示。緩沖區(qū)陣列中共有 10 個緩沖區(qū),任務(wù)通過調(diào)用申請緩沖區(qū)函數(shù) BufReq()向緩沖

50、區(qū)管理方申請得到緩沖區(qū)使用權(quán)。當(dāng)緩沖區(qū)使用權(quán)還不再需要時,通過調(diào)用釋放緩沖區(qū)函數(shù) BufRel()將緩沖區(qū)還給管方。函數(shù)示意碼如程序清單 2.9 所示程序清單程序清單 2.92.9 用信號量管理緩沖區(qū)。用信號量管理緩沖區(qū)。BUF *BufReq(void) BUF *ptr; Acquire a semaphore;20 Disable interrupts; ptr = BufFreeList; BufFreeList = ptr-BufNext; Enable interrupts; return (ptr);void BufRel(BUF *ptr) Disable interrupts

51、; ptr-BufNext = BufFreeList; BufFreeList = ptr; Enable interrupts; Release semaphore;圖 2.12 計數(shù)式信號量的用法緩沖區(qū)陣列管理方滿足前十個申請緩沖區(qū)的任務(wù),就好像有 10 把鑰匙可以發(fā)給諸任務(wù)。當(dāng)所有的鑰匙都用完了,申請緩沖區(qū)的任務(wù)被掛起,直到信號量重新變?yōu)橛行А>彌_區(qū)管21理程序在處理鏈表指針時,為滿足互斥條件,中斷是關(guān)掉的(這一操作非常快)。任務(wù)使用完某一緩沖區(qū),通過調(diào)用緩沖區(qū)釋放函數(shù) BufRel()將緩沖區(qū)還給系統(tǒng)。系統(tǒng)先將該緩沖區(qū)指針插入到空閑緩沖區(qū)鏈表中(Linked list)然后再給信號量

52、加 1 或釋放該信號量。這一過程隱含在緩沖區(qū)管理程序 BufReq()和 BufRel()之中,調(diào)用這兩個函數(shù)的任務(wù)不用管函數(shù)內(nèi)部的詳細(xì)過程。2.19 死鎖死鎖( (或抱死或抱死) )(DeadlockDeadlock (or(or DeadlyDeadly Embrace)Embrace))死鎖也稱作抱死,指兩個任務(wù)無限期地互相等待對方控制著的資源。設(shè)任務(wù) T1 正獨享資源 R1,任務(wù) T2 在獨享資源 T2,而此時 T1 又要獨享 R2,T2 也要獨享 R1,于是哪個任務(wù)都沒法繼續(xù)執(zhí)行了,發(fā)生了死鎖。最簡單的防止發(fā)生死鎖的方法是讓每個任務(wù)都:先得到全部需要的資源再做下一步的工作用同樣的順序

53、去申請多個資源釋放資源時使用相反的順序內(nèi)核大多允許用戶在申請信號量時定義等待超時,以此化解死鎖。當(dāng)?shù)却龝r間超過了某一確定值,信號量還是無效狀態(tài),就會返回某種形式的出現(xiàn)超時錯誤的代碼,這個出錯代碼告知該任務(wù),不是得到了資源使用權(quán),而是系統(tǒng)錯誤。死鎖一般發(fā)生在大型多任務(wù)系統(tǒng)中,在嵌入式系統(tǒng)中不易出現(xiàn)。2.20 同步同步可以利用信號量使某任務(wù)與中斷服務(wù)同步(或者是與另一個任務(wù)同步,這兩個任務(wù)間沒有數(shù)據(jù)交換)。如圖 2.13 所示。注意,圖中用一面旗幟,或稱作一個標(biāo)志表示信號量。這個標(biāo)志表示某一事件的發(fā)生(不再是一把用來保證互斥條件的鑰匙)。用來實現(xiàn)同步機制的信號量初始化成 0,信號量用于這種類型同步

54、的稱作單向同步(unilateral rendezvous)。一個任務(wù)做 I/O 操作,然后等信號回應(yīng)。當(dāng) I/O 操作完成,中斷服務(wù)程序(或另外一個任務(wù))發(fā)出信號,該任務(wù)得到信號后繼續(xù)往下執(zhí)行。22圖 2.13 用信號量使任務(wù)與中斷服務(wù)同步如果內(nèi)核支持計數(shù)式信號量,信號量的值表示尚未得到處理的事件數(shù)。請注意,可能會有一個以上的任務(wù)在等待同一事件的發(fā)生,則這種情況下內(nèi)核會根據(jù)以下原則之一發(fā)信號給相應(yīng)的任務(wù):發(fā)信號給等待事件發(fā)生的任務(wù)中優(yōu)先級最高的任務(wù),或者發(fā)信號給最先開始等待事件發(fā)生的那個任務(wù)根據(jù)不同的應(yīng)用,發(fā)信號以標(biāo)識事件發(fā)生的中斷服務(wù)或任務(wù)也可以是多個。兩個任務(wù)可以用兩個信號量同步它們的行

55、為。如圖 2.14 所示。這叫做雙向同步(bilateral rendezvous)。雙向同步同單向同步類似,只是兩個任務(wù)要相互同步。例如則程序清單 2.10 中,運行到某一處的第一個任務(wù)發(fā)信號給第二個任務(wù)L22.10(1),然后等待信號返回L2.10(2)。同樣,當(dāng)?shù)诙€任務(wù)運行到某一處時發(fā)信號給第一個任務(wù)2.10(3)等待返回信號L2.10(4)。至此,兩個任務(wù)實現(xiàn)了互相同步。在任務(wù)與中斷服務(wù)之間不能使用雙向同步,因為在中斷服務(wù)中不可能等一個信號量。圖 2.14 兩個任務(wù)用信號量同步彼此的行為23程序清單程序清單2.102.10 雙向同步雙向同步Task1() for (;) Perfor

56、m operation; Signal task #2; (1) Wait for signal from task #2; (2) Continue operation; Task2() for (;) Perform operation; Signal task #1; (3) Wait for signal from task #1; (4) Continue operation; 2.21 事件標(biāo)志事件標(biāo)志(Event(Event Flags)Flags)當(dāng)某任務(wù)要與多個事件同步時,要使用事件標(biāo)志。若任務(wù)需要與任何事件之一發(fā)生同步,可稱為獨立型同步(即邏輯或關(guān)系)。任務(wù)也可以與若干事件

57、都發(fā)生了同步,稱之為關(guān)聯(lián)型(邏輯與關(guān)系)。獨立型及關(guān)聯(lián)型同步如圖 2.15 所示。24圖 2.15 獨立型及關(guān)聯(lián)型同步可以用多個事件的組合發(fā)信號給多個任務(wù)。如圖 2.16 所示,典型地,8 個、16 個或32 個事件可以組合在一起,取決于用的哪種內(nèi)核。每個事件占一位(bit),以 32 位的情況為多。任務(wù)或中斷服務(wù)可以給某一位置位或復(fù)位,當(dāng)任務(wù)所需的事件都發(fā)生了,該任務(wù)繼續(xù)執(zhí)行,至于哪個任務(wù)該繼續(xù)執(zhí)行了,是在一組新的事件發(fā)生時辨定的。也就是在事件位置位時做辨斷。內(nèi)核支持事件標(biāo)志,提供事件標(biāo)志置位、事件標(biāo)志清零和等待事件標(biāo)志等服務(wù)。事件標(biāo)志可以是獨立型或組合型。C/OS-目前不支持事件標(biāo)志.2.

58、22 任務(wù)間的通訊任務(wù)間的通訊(Intertask(Intertask Communication)Communication)有時很需要任務(wù)間的或中斷服務(wù)與任務(wù)間的通訊。這種信息傳遞稱為任務(wù)間的通訊。任務(wù)間信息的傳遞有兩個途徑:通過全程變量或發(fā)消息給另一個任務(wù)。用全程變量時,必須保證每個任務(wù)或中斷服務(wù)程序獨享該變量。中斷服務(wù)中保證獨享的唯一辦法是關(guān)中斷。如果兩個任務(wù)共享某變量,各任務(wù)實現(xiàn)獨享該變量的辦法可以是關(guān)中斷再開中斷,或使用信號量(如前面提到的那樣)。請注意,任務(wù)只能通過全程變量與中斷服務(wù)程序通訊,而任務(wù)并不知道什么時候全程變量被中斷服務(wù)程序修改了,除非中斷程序以信號量方式向任務(wù)發(fā)信號

59、或者是該任務(wù)以查詢方式不斷周期性地查詢變量的值。要避免這種情況,用戶可以考慮使用郵箱或消息隊列。25圖 2.16 事件標(biāo)志2.23 消息郵箱消息郵箱(Message(Message MailMail boxes)boxes)通過內(nèi)核服務(wù)可以給任務(wù)發(fā)送消息。典型的消息郵箱也稱作交換消息,是用一個指針型變量,通過內(nèi)核服務(wù),一個任務(wù)或一個中斷服務(wù)程序可以把一則消息(即一個指針)放到郵箱里去。同樣,一個或多個任務(wù)可以通過內(nèi)核服務(wù)接收這則消息。發(fā)送消息的任務(wù)和接收消息的任務(wù)約定,該指針指向的內(nèi)容就是那則消息。每個郵箱有相應(yīng)的正在等待消息的任務(wù)列表,要得到消息的任務(wù)會因為郵箱是空的而被掛起,且被記錄到等待

60、消息的任務(wù)表中,直到收到消息。一般地說,內(nèi)核允許用戶定義等待超時,等待消息的時間超過了,仍然沒有收到該消息,這任務(wù)進(jìn)入就緒態(tài),并返回出錯信息,報告等待超時錯誤。消息放入郵箱后,或者是把消息傳給等待消息的任務(wù)表中優(yōu)先級最高的那個任務(wù)(基于優(yōu)先級),或者是將消息傳給最先開始等待消息的任務(wù)(基于先進(jìn)先出)。圖 2.17 示意把消息放入郵箱。用一個 I 字表示郵箱,旁邊的小砂漏表示超時計時器,計時器旁邊的數(shù)字表示定時器設(shè)定值,即任務(wù)最長可以等多少個時鐘節(jié)拍(Clock Ticks),關(guān)于時鐘節(jié)拍以后會講到。內(nèi)核一般提供以下郵箱服務(wù):郵箱內(nèi)消息的內(nèi)容初始化,郵箱里最初可以有,也可以沒有消息將消息放入郵箱(POS

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論