文獻標識碼: A
μC/OS-II是由Jean Labrosse編寫的具有高度可移植性且源碼公開的嵌入式實時操作系統(tǒng)內(nèi)核,可用于8 bit、16 bit、32 bit嵌入式微處理器或DSP中。μC/OS-II可以管理64個任務(wù),各任務(wù)有自己單獨的棧,采用基于優(yōu)先級的可搶占式PBP(Priority Based Preemptive)調(diào)度策略,絕大多數(shù)服務(wù)的執(zhí)行時間具有確定性μC/OS-II已被成功地應(yīng)用于各種系統(tǒng),在眾多領(lǐng)域中,多種基于μC/OS-II設(shè)計的產(chǎn)品已經(jīng)證明了μC/OS-II內(nèi)核的穩(wěn)定性,其安全性和穩(wěn)定性已通過美國FAA認證。
μC/OS-II操作系統(tǒng)同時也是可剝奪型內(nèi)核,以保證最重要的進程(通常是優(yōu)先級最高的進程)能夠及時得到運行。但是如果用傳統(tǒng)的信號量等機制對共享資源進行互斥操作,在某些時間里會出現(xiàn)高優(yōu)先級進程被低優(yōu)先級進程堵塞的現(xiàn)象,這種現(xiàn)象稱為優(yōu)先級反轉(zhuǎn)。本文討論優(yōu)先級反轉(zhuǎn)現(xiàn)象的原因,并給出2種抑制優(yōu)先級反轉(zhuǎn)現(xiàn)象的具體方法。
1 優(yōu)先級反轉(zhuǎn)現(xiàn)象
使用實時內(nèi)核,優(yōu)先級反轉(zhuǎn)問題是實時系統(tǒng)中出現(xiàn)最多的問題。優(yōu)先級反轉(zhuǎn)發(fā)生在一個高優(yōu)先級的任務(wù)被迫等待一段不確定時間的過程中[1]。優(yōu)先級反轉(zhuǎn)現(xiàn)象示意圖如圖1。
圖1中,空白框為任務(wù)正常運行過程;陰影框為任務(wù)取得信號量后的運行過程。在圖中3個任務(wù)優(yōu)先級的高低為T1>T2>T3,T1和T3在運行過程中都需要使用同一資源,T2不需要使用該資源。當(dāng)T3先占用該資源,T1任務(wù)需要等待,直到T3任務(wù)釋放占用的共享資源。由于T2的優(yōu)先級比T3高,所以剝奪了T3的CPU使用權(quán),使得T3釋放信號量的時間向后拖延,所以T1的運行情況更加惡化,T1取得信號量的時間隨之推遲。這樣,原本優(yōu)先級最高的T1任務(wù),在經(jīng)過以上過程后,優(yōu)先級反而降到了最低。這時,系統(tǒng)中就發(fā)生了優(yōu)先級反轉(zhuǎn)的現(xiàn)象。
優(yōu)先級反轉(zhuǎn)原因可歸納為:高優(yōu)先級的任務(wù)由于要等待被低優(yōu)先級任務(wù)占有的臨界資源而被中優(yōu)先級任務(wù)阻塞,而此時具有中優(yōu)先級的任務(wù)搶占了低優(yōu)先級任務(wù)的CPU時間,導(dǎo)致具有中優(yōu)先級的任務(wù)先于高優(yōu)先級任務(wù)而執(zhí)行。
2 優(yōu)先級反轉(zhuǎn)的解決方案
優(yōu)先級反轉(zhuǎn)問題的解決辦法有優(yōu)先級置頂和優(yōu)先級繼承2種[2]。
采用優(yōu)先級置頂?shù)姆桨?,首先在?chuàng)建互斥信號量時就應(yīng)同時設(shè)置一個相應(yīng)的置頂優(yōu)先級,當(dāng)首先申請到該資源的任務(wù)a未釋放而又有一個更高優(yōu)先級的任務(wù)b試圖申請時,內(nèi)核會將任務(wù)a的優(yōu)先級提升到置頂優(yōu)先級,該置頂優(yōu)先級高于任何可能申請該資源任務(wù)的高優(yōu)先級。優(yōu)先級置頂?shù)囊饬x在于使占有資源的低優(yōu)先級任務(wù)盡快完成,讓高優(yōu)先級任務(wù)的等待不至過長。
而優(yōu)先級繼承的思想是:在出現(xiàn)上述情況時,提高低優(yōu)先級任務(wù)的優(yōu)先級使其與高優(yōu)先級任務(wù)的優(yōu)先級等同。而μC/OS-II卻不支持這種方法[3],需要通過修改μC/OS-II內(nèi)核來實現(xiàn)優(yōu)先級繼承。
2.1 優(yōu)先級置頂方案
要在μC/OS-II實現(xiàn)優(yōu)先級置頂[4],需要用到互斥信號量(Mutex)。
互斥型信號量的創(chuàng)建是由函數(shù)OSMutexCreate( )完成的,它首先檢查PCP的優(yōu)先級數(shù)值是否己經(jīng)被其他任務(wù)使用,如果還沒有使用就占用這個優(yōu)先級。然后得到一個新的事件控制塊ECB,OSMutexCreate( )置mutex的值為有效,同時將PCP保存起來。
OSMutexPend( )函數(shù)在獲取互斥信號量Mutex時,如果Mutex可用,并且占有信號量任務(wù)的優(yōu)先級不是最高,則提升此任務(wù)的優(yōu)先級置PIP,即置頂優(yōu)先級,使它盡快執(zhí)行并退出臨界區(qū)從而釋放Mutex。釋放信號量函數(shù)OSMutexPost( )則是將當(dāng)前任務(wù)的優(yōu)先級恢復(fù)原值,并檢查是否有任務(wù)仍在申請該資源。
利用優(yōu)先級置頂解決前面提到的優(yōu)先級反轉(zhuǎn)的過程如圖2所示。
以開始系統(tǒng)初始化,直到T1任務(wù)開始請求信號量的時刻,系統(tǒng)運行情況和應(yīng)用普通信號量時的情況是一致的。t2時刻,T1任務(wù)開始啟動,請求信號量,此時系統(tǒng)得知T1任務(wù)所需的信號量正在被T3任務(wù)所占據(jù),故提高T3任務(wù)的優(yōu)先級,使之高于請求該信號量的所有任務(wù)的優(yōu)先級;t3時刻,T1任務(wù)由于得不到信號量而被掛起,此時由于T3任務(wù)的優(yōu)先級高于T1和T2任務(wù),所以系統(tǒng)讓T3任務(wù)先完成,從而釋放信號量。當(dāng)T3任務(wù)釋放信號量的時候,系統(tǒng)得知T3任務(wù)的優(yōu)先級是被暫時提高的,所以恢復(fù)T3任務(wù)的優(yōu)先級,此時T1任務(wù)可以請求并得到信號量;t4時刻,T1任務(wù)由于得到信號量而開始運行;t5時刻,T1任務(wù)運行完畢,由系統(tǒng)切換任務(wù),使T2任務(wù)開始運行。在一定程度上抑制了優(yōu)先級反轉(zhuǎn)。在μC/OS-II系統(tǒng)中建立如上所述的3個任務(wù),作用時分別輸出格式為“自己的任務(wù)名稱is running”的字符串。使用了互斥信號量后的實驗結(jié)果如圖3所示。
2.2 優(yōu)先級繼承方案
在μC/OS-II中,由于不同的任務(wù)不能對應(yīng)同一個優(yōu)先級,所以不支持上述方法。不過,可以通過修改操作系統(tǒng)的內(nèi)核,使之成為可能,從而用優(yōu)先級繼承的方案解決優(yōu)先級反轉(zhuǎn)現(xiàn)象。這里采用類似于時間片輪番調(diào)度法的方案,在同一優(yōu)先級上對不同任務(wù)進行調(diào)度。
這種方法給處于同一優(yōu)先級的不同任務(wù)都分配一個時間片,當(dāng)內(nèi)核運行到某一任務(wù)時,對同優(yōu)先級且處于就緒態(tài)的任務(wù)依次進行調(diào)度,即當(dāng)就緒態(tài)中先到的任務(wù)用完自己的時間片后,CPU控制權(quán)轉(zhuǎn)讓給就緒態(tài)中后一任務(wù)。該任務(wù)用完自己的時間片后,CPU控制權(quán)又轉(zhuǎn)讓給后一個就緒態(tài)任務(wù)。當(dāng)就緒態(tài)的每一個任務(wù)都被調(diào)度一次之后將重新為它們分配時間片,然后又開始新周期的調(diào)度。在調(diào)度過程中如果有一個比當(dāng)前任務(wù)優(yōu)先級更高的任務(wù)由其他態(tài)變成了就緒態(tài)(被創(chuàng)建或獲取了一個信號量等等),當(dāng)前任務(wù)的CPU控制權(quán)將被剝奪;空閑任務(wù)仍然是等到其他任務(wù)都退出就緒態(tài)才獲得CPU使用權(quán)。
這種方法的優(yōu)點不僅體現(xiàn)在可以讓同一優(yōu)先級對應(yīng)不同的任務(wù),從而進行優(yōu)先級繼承,還體現(xiàn)在可以增加操作系統(tǒng)調(diào)度任務(wù)的最大數(shù)目,這使應(yīng)用系統(tǒng)的開發(fā)更加靈活。因為在不允許一個優(yōu)先級對應(yīng)不同任務(wù)的μC/OS-II中,用戶能夠自己創(chuàng)建的任務(wù)數(shù)目最多為56個。
在μC/OS-II中,實現(xiàn)優(yōu)先級繼承方案應(yīng)該首先在任務(wù)控制塊(TCB)的結(jié)構(gòu)體中添加構(gòu)成雙向鏈表的前驅(qū)節(jié)點指針(變量名為OSMYnext)、后繼結(jié)點指針(變量名為OSMYprev)和2個用于指示時間的變量(OSMYtime和OSMYtimeremain)。指針的作用是用來查找同一優(yōu)先級的不同任務(wù),便于添加新任務(wù)和刪除已經(jīng)釋放了信號量的任務(wù)。在沒有其他任務(wù)和自己處于同一優(yōu)先級的狀態(tài)下,鏈表的前后指針均指向自己。變量OSMYtime的作用表示分給該任務(wù)的時間片長度,OSMYtimeremain表示當(dāng)前時間片剩余時間。
由于當(dāng)前任務(wù)的時間片使用完時,就會被從就緒表OSRdyGrp以及OSRdyTbl[ ]中清除,這樣,正常的調(diào)度將被打亂,所以還需增加保存臨時OSRdyGrp和OSRdyTbl[ ]的變量OSTempGrp和OSTempTbl[ ]。由于在創(chuàng)建任務(wù)時μC/OS-II會比較該任務(wù)和已建立的任務(wù)的優(yōu)先級是否相同,所以還需把任務(wù)創(chuàng)建函數(shù)中相應(yīng)代碼進行屏蔽。
時鐘節(jié)拍函數(shù)OSTimeTick( )在時間片調(diào)度過程中起到了修改時間片計數(shù)器的作用,每一次時鐘節(jié)拍的到來都會引起時間片的減少。在OSTimeTick( )函數(shù)中,主要完成以下工作:首先檢查同優(yōu)先級的雙向鏈表指針是否指向自己。如果指向自己,則說明在這一優(yōu)先級上,只有自己一個任務(wù)。如果指向其他的任務(wù),則要通過遞減正在運行的任務(wù)的時間片來確定分給該任務(wù)的時間片是否用完。
如果時間片沒有用完,則執(zhí)行OS_Sched()函數(shù),讓內(nèi)核進行調(diào)度;如果時間片已經(jīng)用完,則讓時間片重新賦值,然后同樣進行調(diào)度,在沒有更高優(yōu)先級的任務(wù)處于就緒態(tài)時,系統(tǒng)將運行鏈表所指示的下一個任務(wù)。其主要步驟的流程圖如圖4所示。
經(jīng)過以上步驟,就可以在μC/OS-II系統(tǒng)中基本實現(xiàn)時間片輪番調(diào)度,不過要想解決優(yōu)先級反轉(zhuǎn)的問題,還需要做以下工作。
當(dāng)一個任務(wù)進入等待互斥信號量OSMutexPend( )函數(shù)時,首先判斷當(dāng)前任務(wù)的優(yōu)先級是否高于已經(jīng)得到并且還沒釋放該資源的任務(wù)優(yōu)先級。如果當(dāng)前的任務(wù)優(yōu)先級高,則要將得到該資源的任務(wù)優(yōu)先級提到當(dāng)前任務(wù)的優(yōu)先級水平,并且把當(dāng)前任務(wù)加到自己的雙向鏈表中,再執(zhí)行一次內(nèi)核調(diào)度。
當(dāng)任務(wù)執(zhí)行OSMutexPost( )釋放互斥信號量時,如果在其擁有信號量的過程中被提升過優(yōu)先級,則將恢復(fù)之前的優(yōu)先級。然后查看是否還有任務(wù)在等待該信號量,準備下一次調(diào)度。
用優(yōu)先級繼承的方法測試,同樣選取T1、T2、T3 3個任務(wù),進行同優(yōu)先級置頂方案相同的實驗,得到如圖5所示的結(jié)果。
從圖5可以看出,用時間片解決優(yōu)先級反轉(zhuǎn)的效果與優(yōu)先級置頂大致相同,區(qū)別僅在于當(dāng)T3任務(wù)取得資源運行時,時間片用完后,T1任務(wù)又開始申請該資源,而T3并未放棄,所以出現(xiàn)如圖5的結(jié)果。如果T3的時間片設(shè)置過小,這一過程就將頻繁發(fā)生,從而降低了效率。所以如果系統(tǒng)當(dāng)前的任務(wù)集合相對簡單,則在發(fā)生優(yōu)先級反轉(zhuǎn)時,把低優(yōu)先級任務(wù)的時間片調(diào)大一些為好。
運用時間片輪番調(diào)度法,解決了在μC/OS-II系統(tǒng)中實現(xiàn)優(yōu)先級繼承的方案,在一定程度上抑制了優(yōu)先級反轉(zhuǎn)現(xiàn)象,提高了系統(tǒng)的實時性,還增加了系統(tǒng)同時運行任務(wù)的最大數(shù)目,提高了系統(tǒng)的運行效率。
優(yōu)先級反轉(zhuǎn)是任何一個多任務(wù)實時操作系統(tǒng)都無法避免的問題。本文分析了該現(xiàn)象產(chǎn)生的原因,主要討論了μC/OS-II中運用mutex和時間片輪番調(diào)度解決該問題的方法并對其可行性進行了驗證。相對優(yōu)先級繼承和優(yōu)先級置頂策略,在可能出現(xiàn)優(yōu)先級反轉(zhuǎn)的情況下,動態(tài)地改變?nèi)蝿?wù)優(yōu)先級能夠保證高優(yōu)先級任務(wù)的執(zhí)行,有效提高了系統(tǒng)的實時性。
參考文獻
[1] 楊宗德,張兵μC/OS-II標準教程[M].北京:人民郵電出版社,2009:153-156.
[2] LABROSSE J.μC/OS-II the real-time kernel[M].Lawrence,R&D Books,2003:47-64.
[3] LABROSSE J J.嵌入式實時操作系統(tǒng)μC/OS-II(第2版) [M].北京:北京航空航天大學(xué)出版社,2003:44-46.
[4] 任哲.嵌入式實時操作系統(tǒng)μC/OS-II原理及應(yīng)用[M].北京:北京航空航天大學(xué)出版社,2005:124-130