轉自 :http://www.cnblogs.com/scdyxcc/p/3290340.html?utm_source=tuicool
1、在ucos-ii中,有這麼幾張表來管理任務。
A、OSTCBPrioTbl[],其結構為OS_TCB指針的數組,其元素個數為64, 每一個元素對應一個任務的優先級,ucos-ii最多可以有64個任務,是以當有任務建立的時候,其每一個元素均指向一個任務控制塊(若相應的優先級,已經建立了任務的話);若相應的優先級沒有建立任務,則該數組元素指向的是(OS_TCB *)0;
B、任務控制塊連結清單,該連結清單的每個節點,都是OS_TCB型結構。任務控制塊連結清單除了本身構成一個雙向連結清單, 其還與OSTCBPrioTbl[](OSTCBPrioTbl[]存放的就是任務控制塊的首位址)和任務堆棧相聯系(通過OS_TCB結構的OSTCBStkPtr元素指向任務堆棧的棧頂來實作)。在建立一個任務的時候,都必須建立任務控制塊置于任務控制塊連結清單中,通過OSTCBList來實作将其放于任務控制塊連結清單的開頭即建立的任務控制塊。
C、任務就緒表,為9個位元組,(OSRdyGrp和OSRdyTbl[8]).
OSRdyGrp存放的優先級分組的号。若其中的有一位置1, 表明其有任務處于就緒狀态,若為0表示沒有任務處于就緒狀态。假設OSRdyGrp的第i位為1, 則表示處于任務優先級(i-1)*8~i*8-1中,至少有一個任務的處于就緒态(其中i屬于(1~8))。
OSRdyTbl[8]的每個元素為8位,每一位代表一個任務優先級。這樣8*8剛好為64,是以剛好可以存放完ucos-ii的最大任務總數。在該數組中,根據每位的值為0/1來決定其對應優先級的任務是否處于就緒态。為0表示該優先級任務不處于就緒狀态,為1表示處于就緒态。同時當OSRdyTbl[]有一位為1時,該位代表的優先級将OSRdyGrp中對應的為置1。
由于ucos-ii為實時系統,為了盡量縮短查找表所用的時間,其還定義了兩個常數數組,一個為OSMapTbl[8]和OSUnMapTbl[256]。(我個人認為這兩個數組的設計最為巧妙和最有價值),通過這兩張表很友善的就可以查詢是否有任務處于就緒态,處于就緒态的最高優先級是多少。并且将一個任務置于就緒狀态或者進行任務的排程都需要利用這兩個常數數組。
OSMapTbl[]表如圖1所示:
OSUnMapTbl[]表如圖2所示:
D、空任務控制塊連結清單,用來管理空任務控制塊。當建立任務時,需要從該連結清單擷取一個OS_TCB, 并将其放于任務控制塊連結清單中。在這過程中主要是通過兩個OS_TCB指針來完成,一個是OSTCBFreelist,另一個是OSTCBList,這兩個指針始終指向連結清單的開頭。
2、任務的建立過程
通過函數OSTaskCreate()或者OSTaskCreateEXT()兩個函數來建立一個任務。
A、能否建立成功取決于這麼幾個條件:
a) 配置設定給即将要建立任務的優先級是否合法,prio<63(或者為自己修改的最大任務數);
b) 配置設定給将要建立任務的優先級是否已經被已存任務所占用,若沒有被占用,則将OSTCBPrioTbl[prio]指派1,來占用該優先級;
c) 是否有足夠的RAM來配置設定給任務,作為任務的私有堆棧;
d) 是否有空餘的OS_TCB配置設定給任務,作為該任務的任務控制塊;
B、任務建立完後,上面所提到的有關任務控制塊的幾張表的更新。
a) OSTCBPrioTbl[]表:将新建立任務的任務控制塊首位址存放在相應任務優先級元素中(即OSTCBPrioTbl[prio]中)。
b) 任務控制塊連結清單:将OSTCBList指針更新指向建立的任務控制塊,另外通過OS_TCB結構中的OSTCBNext和OSTCBPrev成員,将建立任務的OS_TCB置于雙向連結清單中。
c) 任務就緒表的更新:建立任務建完後為就緒狀态,是以應該将任務優先級在任務就緒表中相應的位置1, 其實作方式通過以下兩條指令實作:OSRdyGrp |=OSMapTbl[prio>>3];
OSRdyTbl[prio>>3] |=OSMapTbl[prio & 0x07];
d) 空任務控制塊連結清單:因為建立任務必須從空任務控制塊中取出,是以在取完空OS_TCB需後,要修改OSTCBFreeList指針,将其指向下一個空OS_TCB。
C) 任務建立完後,與任務相關參數的設定。
任務的OS_TCB 存放在OSTCBPrioTbl[prio]中,任務的私有堆棧資訊(棧頂指針、棧底指針和堆棧大小)存放在任務的OS_TCB中。任務函數的首位址存放在任務的堆棧中。
3、任務排程
A) 任務排程發生的時間
a)系統剛啟動,完成初始化和至少建立了一個任務後,通過OSStart()函數調用__OSStartHighRdy函數将OSRunning=TRUE後,通過任務切換函數OSCtxSw來啟動。
b) 系統運作過程中,建立任務的時需要啟動任務排程器OSSched(),進行任務排程。
c) 任務被挂起或者等待延時或者等待其他時間發生時,需要進行任務排程。
d) 任務在運作過程中,有更高優先級任務處于就緒狀态時,需要進行任務的排程(通過定時器中斷服務程式,查詢和更新所有任務狀态時發現其是否有更高優先級任務處于就緒态)。
e) 中斷服務程式運作過程中(ISR中需要使用任務)或者運作完之後需要進行任務的排程。
B) 怎樣找到任務并運作
第一步:通過任務排程器或其他的方式,獲得任務中的最高優先級prio;
第二步:通過prio在OSTCBPrioTbl[]中查找與prio相應的任務控制塊,因為OSTCBPrioTbl[prio]中存放的就是與prio對應的OS_TCB,是以很容易就知道找到該OS_TCB。
第三步:獲得任務的OS_TCB後,通過任務控制塊中存放的有關堆棧資訊來找到任務的私有堆棧。在堆棧中,将任務私有堆棧存放的有關處理器寄存器的内容恢複,則開始運作該任務。
在這過程中,有幾個地方要記住:
1) 運作任務前,應該将其優先級在任務就緒表中相應的為清零;
2) 必須儲存前一任務的資訊;