文獻(xiàn)標(biāo)識碼: 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認(rèn)證,。
μC/OS-II操作系統(tǒng)同時也是可剝奪型內(nèi)核,,以保證最重要的進(jìn)程(通常是優(yōu)先級最高的進(jìn)程)能夠及時得到運行。但是如果用傳統(tǒng)的信號量等機(jī)制對共享資源進(jìn)行互斥操作,,在某些時間里會出現(xiàn)高優(yōu)先級進(jìn)程被低優(yōu)先級進(jìn)程堵塞的現(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ù)進(jìn)行調(diào)度,。
這種方法給處于同一優(yōu)先級的不同任務(wù)都分配一個時間片,當(dāng)內(nèi)核運行到某一任務(wù)時,,對同優(yōu)先級且處于就緒態(tài)的任務(wù)依次進(jìn)行調(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ù),從而進(jìn)行優(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)代碼進(jìn)行屏蔽,。
時鐘節(jié)拍函數(shù)OSTimeTick( )在時間片調(diào)度過程中起到了修改時間片計數(shù)器的作用,每一次時鐘節(jié)拍的到來都會引起時間片的減少,。在OSTimeTick( )函數(shù)中,,主要完成以下工作:首先檢查同優(yōu)先級的雙向鏈表指針是否指向自己。如果指向自己,,則說明在這一優(yōu)先級上,,只有自己一個任務(wù)。如果指向其他的任務(wù),,則要通過遞減正在運行的任務(wù)的時間片來確定分給該任務(wù)的時間片是否用完,。
如果時間片沒有用完,則執(zhí)行OS_Sched()函數(shù),,讓內(nèi)核進(jìn)行調(diào)度,;如果時間片已經(jīng)用完,則讓時間片重新賦值,,然后同樣進(jìn)行調(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ù)進(jìn)入等待互斥信號量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ù)在等待該信號量,準(zhǔn)備下一次調(diào)度,。
用優(yōu)先級繼承的方法測試,,同樣選取T1、T2,、T3 3個任務(wù),,進(jìn)行同優(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)度解決該問題的方法并對其可行性進(jìn)行了驗證,。相對優(yōu)先級繼承和優(yōu)先級置頂策略,在可能出現(xiàn)優(yōu)先級反轉(zhuǎn)的情況下,,動態(tài)地改變?nèi)蝿?wù)優(yōu)先級能夠保證高優(yōu)先級任務(wù)的執(zhí)行,,有效提高了系統(tǒng)的實時性。
參考文獻(xiàn)
[1] 楊宗德,,張兵μC/OS-II標(biāo)準(zhǔn)教程[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