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