曹雷欣 孔祥坤
【關(guān)鍵詞】uC/OS-II任務(wù);多任務(wù)切換;信號量機制;任務(wù)TCB;Task控制塊
(一)uC/OS-II其任務(wù)建立一般在多任務(wù)運行前,子任務(wù)也可以動態(tài)地被運行著的任務(wù)建立。如果該任務(wù)被另一個未運行任務(wù)所建,兩個任務(wù)中高優(yōu)先級任務(wù)將取得CPU的控制權(quán)。
(二)一個任務(wù)被創(chuàng)建后,可能處在以下五種狀態(tài):
休眠態(tài)(Dormant State)指任務(wù)被調(diào)到內(nèi)存中準(zhǔn)備運行,但還沒有被uC/OS-II內(nèi)核轉(zhuǎn)讓管理權(quán)時的狀態(tài)。
任務(wù)就緒態(tài)(Ready State)指將要運行的任務(wù)準(zhǔn)備就緒,即將開始運行。
任務(wù)等待態(tài)(Waiting State)指等待一段時間然后將會被調(diào)用進入運行狀態(tài)。
中斷服務(wù)狀態(tài)(Interrupt Service State)指任務(wù)因高優(yōu)先級任務(wù)搶占被中斷執(zhí)行,被迫進入中斷服務(wù)例程的狀態(tài)。
執(zhí)行狀態(tài)(Executive state)指任務(wù)正處于運行的狀態(tài)。
(一)就緒態(tài)、運行態(tài)、等待態(tài)轉(zhuǎn)為休眠態(tài)的切換方法:
一個任務(wù)處于就緒狀態(tài)或運行狀態(tài)或等待狀態(tài)時,要想切換到休眠態(tài)需要調(diào)用OSTaskDel()返回到休眠態(tài)。
(二)由睡眠態(tài)進入就緒態(tài)的方法
任務(wù)處于休眠態(tài)要調(diào)用OSTaskCreate()或OSTaskCreateExt0函數(shù),這樣就可以把任務(wù)交給uC/OS-II內(nèi)核管理,同時進入就緒態(tài)狀態(tài)( Ready State),準(zhǔn)備運行。
(三)由運行態(tài)進入等待狀態(tài)的方法
任務(wù)要想進入運行態(tài)需要OSTimeDly()或OSTimeDlyHMSMO函數(shù)方法,任務(wù)進入運行態(tài)將等待下一個優(yōu)先級更高的、達(dá)到了就緒態(tài)的任務(wù)到來,并轉(zhuǎn)入CPU控制權(quán)。
將運行態(tài)的任務(wù)變換成等待某一事件發(fā)生的等待態(tài)(WAITING State)需要調(diào)用OSSemPend(),OSMboxPend0,或OSQPend0函數(shù)。掛起任務(wù)(PendTask),由于等待事件或所需資源沒有就緒,CPU的控制權(quán)會被下一個優(yōu)先級更高的、提前進入就狀態(tài)緒態(tài)的任務(wù)搶占。
(四)由等待狀態(tài)進入就緒態(tài)
uC/OS-II系統(tǒng)服務(wù)函數(shù)OSTimeTick()發(fā)現(xiàn)處于等待態(tài)的任務(wù)等待時間片耗盡后,會切換任務(wù)進入到就緒態(tài)。之前被掛起的任務(wù)發(fā)現(xiàn)等待的事件發(fā)生了(所需資源被釋放),也將進入就緒態(tài)。這種消息可能來自系統(tǒng)的中斷服務(wù)例程或自某一個任務(wù)。
(五)運行狀態(tài)與中斷狀態(tài)之間的相互轉(zhuǎn)換
一個處于運行狀態(tài)的任務(wù)被內(nèi)部或外部的中斷了就進入了中斷服務(wù)態(tài)(ISR)。子中斷服務(wù)程序當(dāng)執(zhí)行的任務(wù)被掛起時會交還CPU的使用權(quán)。
處于中斷狀態(tài)的任務(wù)當(dāng)中斷服務(wù)子程序執(zhí)行完返回后系統(tǒng)將會調(diào)用OSlnext()函數(shù)使優(yōu)先級最高的并進入就緒狀態(tài)的任務(wù)得以運行。
(六)就緒狀態(tài)與運行狀態(tài)的相互轉(zhuǎn)換
任務(wù)在處于就緒態(tài)時,當(dāng)系統(tǒng)調(diào)度OSStart()函數(shù)執(zhí)行時,就進入了運行態(tài)。
一個正在運行的狀態(tài)由于某種原因它的CPU使用權(quán)被剝奪時就進入了就緒狀態(tài)。
(七)任務(wù)狀態(tài)之間相互轉(zhuǎn)換的關(guān)系在uC/OS-II中如圖1所示。
(一)多任務(wù)之間通信,在uC/OS-II系統(tǒng)中主要考慮了兩個問題:
Task(任務(wù))之間可以共享資源,但在資源訪問上是一種互斥關(guān)系,是一種獨占式的共享。正在執(zhí)行的任務(wù)在沒有釋放獨占資源時,其他任務(wù)則只能等待;當(dāng)任務(wù)獲得任務(wù)執(zhí)行所需事件及資源都具備后,等待當(dāng)前任務(wù)結(jié)束會順序執(zhí)行,否則任務(wù)只能循環(huán)等待。
(二)任務(wù)間的通信
1、事件
uC/OS-II任務(wù)之間實現(xiàn)通信的媒介包括信號量、消息隊列和消息郵箱。事件之間的通信包括發(fā)送事件、請求事件,其操作就是任務(wù)把信息從一個事件發(fā)送到另一個事件上。請求事件又被叫做讀取事件,或者稱之為等待事件。
2、信號量
信號量本質(zhì)上說是事件,是uC/OS-II中實現(xiàn)任務(wù)間通信的一種機制設(shè)置。信號量的機制中有一種二值形式的信號量(兩種狀態(tài)),可以實現(xiàn)資源的獨占式共享,又叫做互斥型的信號量,其余信號量機制還有計數(shù)式信號量等。
在信號量機制的設(shè)計上,是基于打破請求保持的死鎖條件的考慮。為防止任務(wù)間因相互持有對方任務(wù)執(zhí)行所必需的資源,且繼續(xù)請求其他所需資源,造成多個任務(wù)都無法得到執(zhí)行的情況發(fā)生,因此在等待信號量的時間上規(guī)定了一個時限,即等待時限。當(dāng)任務(wù)等待時間超過規(guī)定,仍未等到這個信號,就強制命令該任務(wù)停止等待,釋放所保持資源。
在以優(yōu)先級作為調(diào)度依據(jù)的可搶占式實時操作系統(tǒng)uC/OS-II的核心代碼中,優(yōu)先級的高低完全決定了任務(wù)獲得CPU使用權(quán)的先后順序。系統(tǒng)依據(jù)信號量獲得與否,決定調(diào)度任務(wù)能否被運行。因此在某些使用信號量同步機制的實時任務(wù)中,有兩個限制任務(wù)能否運行的條件:一是任務(wù)優(yōu)先級的高下:二是正在等待信號量的獲得與否。
3、消息郵箱
uC/OS-II實時操作系統(tǒng)中,多任務(wù)間采用消息郵箱傳遞信息,這種方法很好地實現(xiàn)了任務(wù)間的通信。通常,多任務(wù)系統(tǒng)的內(nèi)存中有共享存儲區(qū),以作消息緩沖。對緩沖區(qū)的數(shù)據(jù)存取操作,可以實現(xiàn)任務(wù)間的消息傳遞。消息郵箱的數(shù)據(jù)類型是存取消息的指針型數(shù)據(jù)結(jié)構(gòu)。
4、消息隊列
消息郵箱可以在設(shè)計的時候設(shè)計為多個也可以為單個。多消息郵箱以指針數(shù)組的形式實現(xiàn),一個個數(shù)組元素里存放著消息緩沖區(qū)指針的數(shù)組型數(shù)據(jù)結(jié)構(gòu),就是所謂的消息隊列,消息緩沖區(qū)以指針數(shù)組的方式一次實現(xiàn)多個消息傳遞。
(一)任務(wù)就緒表
uc/OS-II總是運行進入就緒狀態(tài)任務(wù)中優(yōu)先級最高的那一個。所有任務(wù)的就緒態(tài)都存放于在一個叫就緒表( Ready List)的數(shù)據(jù)結(jié)構(gòu)中。就緒表是提供給任務(wù)調(diào)度使用的,無需用戶干預(yù),系統(tǒng)會從若干個不同優(yōu)先級的任務(wù)中找出相應(yīng)就緒的任務(wù)進入運行狀態(tài)。
(二)就緒表的構(gòu)成
就緒表由OSRdyGrp和OSRdyTbl[]構(gòu)成,在OSRdyGrp中,任務(wù)按優(yōu)先級分組,8個任務(wù)一組,當(dāng)前系統(tǒng)最多有64個優(yōu)先級,所以O(shè)SRdyGrp有8個有效位,一共可以對應(yīng)8組任務(wù)。每一位對應(yīng)一組任務(wù),第O位對應(yīng)的就是優(yōu)先級0-7的任務(wù),這8個任務(wù)之間是“或”的關(guān)系,只要一個任務(wù)處于就緒狀態(tài),那么OSRdyGrp的第O位就是1,如下圖2所示。
(三)事件的等待任務(wù)列表
uC/OS-II實現(xiàn)事件管理的功能有兩個:一是對等待該事件或資源的所有任務(wù),依據(jù)其到來的先后,對任務(wù)進行記錄和排序;二是對正在等待執(zhí)行的所有任務(wù),允許其在一定時間內(nèi)等待,而不是一直等待。uC/OS-II采用了與任務(wù)就緒表類似的方法實現(xiàn)對于等待事件任務(wù)的記錄和排序,定義一個8位整型( INT8U)有記錄功能的數(shù)組OSEventTbl[],作為等待任務(wù)的記錄表。uC/OS-II在事件機制上,還定義另一個8位整型( INT8U)的變量OSEventGrp,作為等待任務(wù)記錄表中的任務(wù)組。
任務(wù)控制塊( TCB)的成員函數(shù)OSTCBDly可以記錄任務(wù)的等待時件,在下個時鐘節(jié)拍到來時,中斷服務(wù)程序?qū)詣舆M行計數(shù)。當(dāng)出現(xiàn)超時任務(wù)時,TCB則將會把記錄從事件等待任務(wù)表中刪除,并重新恢復(fù)任務(wù)進入就緒態(tài)。
(四)任務(wù)控制塊OS-TCB與任務(wù)棧OS_STK
OS-TCB這種數(shù)據(jù)結(jié)構(gòu),就用來描述任務(wù)所具有的某些屬性的,uC/OS-II將會用它來對各個任務(wù)進行處理:
1、當(dāng)前任務(wù)被建立時,任務(wù)控制塊將被初始化;
2、當(dāng)前任務(wù)CPU使用權(quán)被搶占后,TCB將會保存任務(wù)的狀態(tài);
3、當(dāng)前任務(wù)重新獲得CPU使用權(quán)時,為了確保任務(wù)能夠從中斷之時繼續(xù)執(zhí)行下去,TCB會把保存的數(shù)據(jù)裝載到要執(zhí)行任務(wù)的堆棧中進行恢復(fù)。
由于OS_TCB只有在任務(wù)創(chuàng)建之后才有意義,所以其全部駐留在RAM當(dāng)中。
任務(wù)堆棧(OS_STK)在uC/OS-II中的作用是保存任務(wù)運行時涉及到的資源,例如使用到的寄存器、調(diào)用這個任務(wù)的返回地址,或者是任務(wù)內(nèi)部函數(shù)嵌套時用到的返回地址保存參數(shù)等。
(五)事件控制塊ECB
uC/OS-II中有關(guān)任務(wù)調(diào)度技術(shù)上,設(shè)置了一個事件控制塊( ECB)。ECB的能夠把事件的等待任務(wù)表和與事件有關(guān)的信息捆綁在一起,并定義為事件。ECB這種結(jié)構(gòu)是用來存儲諸如信號量、郵箱(消息郵箱)和消息隊列等事件。
從OSEventTbI[OS_EVENT_TBL_SIZE]其定義來看,其實際為指針數(shù)組,其數(shù)據(jù)類型和任務(wù)就緒表在定義格式上頗似。程序中,所有任務(wù)按照其優(yōu)先級高低,各自在表中占據(jù)一個二進制位,以二值(1或者0)的形式來記錄。該位標(biāo)記對應(yīng)的任務(wù)是否是正在等待事件的任務(wù),標(biāo)記任務(wù)狀態(tài)的這張表又被稱為任務(wù)等待表。
1、事件控制塊的基本函數(shù)操作
TCB基本操作函數(shù),其函數(shù)方法,都定義在內(nèi)核文件OS_CORE.C中,供信號量事件,消息郵箱事件,消息隊列事件來調(diào)用。
(1)事件控制塊的初始化函數(shù)
#if (OS_Q_EN&&(OS_MAX_QS>=2))11 0S_MBOX_EN ll OS_SEM_EN//初始化條件
void OSEventWaitListlnit (OS_EVENT *PREVENT)//指向TCB的指針OS_EVENT *PREVENT
該函數(shù)在任務(wù)調(diào)用OS***Create0函數(shù)時進行事件創(chuàng)建,被OS****Create0函數(shù)作為子函數(shù)調(diào)用。在此指代:Sem,Mutex,Mbox,Q。
(2)切換Task進入等待狀態(tài)的函數(shù)
需要把一個任務(wù)切換成等待狀態(tài),系統(tǒng)會調(diào)用OSEventTaskWait0功能函數(shù)。
#if (OS_Q_EN&&(OS_MAX_QS>=2))11 0S_MBOX_EN|| OS_SEM_EN
void OSEventTaskWait (OS_EVENT*pevent)
上邊的OSEventTaskWait()函數(shù),將在任務(wù)調(diào)用函數(shù)OS***Pend0發(fā)送事件時,被OS***Pend0來調(diào)用。
(3)切換Task進入正在等待就緒狀態(tài)的函數(shù)
在當(dāng)前任務(wù)中,調(diào)用OSEventTaskRdy0函數(shù)把該任務(wù)在Task等待表中所置位清0,等切換出等待狀態(tài)后,任務(wù)就緒表中把該任務(wù)所在的對應(yīng),設(shè)置為1,新一輪的任務(wù)的調(diào)度工作將啟動。
(六)空事件控制塊鏈表
空事件控制塊鏈表其數(shù)據(jù)結(jié)構(gòu)實現(xiàn)上,與管理任務(wù)控制塊的實現(xiàn)方法頗有相似,uC/OS-II把事件控制塊也組織成為兩條鏈表來管理。
uC/OS-II在系統(tǒng)完成初始化后,會在初始化函數(shù)OSlnit0中,按照應(yīng)用程序使用事件總數(shù)的最大值,創(chuàng)建OS_MAX_EVENTS個空事件塊,并以成員OSEventPtr作為鏈接指針組成單向鏈表。
本文簡要介紹了uG/OS-II的多任務(wù)切換方法和uG/OS-II的任務(wù)之間的通信機制。本文初步的對uC/OS-II的初步探究揭示了實時操作系統(tǒng)( RTOS)的多任務(wù)的一般實現(xiàn)途徑,將對研究其他操作系統(tǒng)的多任務(wù)的實現(xiàn)和管理機制的研究有一定的借鑒作用。