ucos-ii的任務調度機制

 一、在ucos-ii中,有這麼幾張表來管理任務。數組

     A、OSTCBPrioTbl[],其結構爲OS_TCB指針的數組,其元素個數爲64, 每個元素對應一個任務的優先級,ucos-ii最多能夠有64個任務,因此當有任務創建的時候,其每個元素均指向一個任務控制塊(若相應的優先級,已經創建了任務的話);若相應的優先級沒有創建任務,則該數組元素指向的是(OS_TCB *)0;函數

      B、任務控制塊鏈表,該鏈表的每一個節點,都是OS_TCB型結構。任務控制塊鏈表除了自己構成一個雙向鏈表, 其還與OSTCBPrioTbl[](OSTCBPrioTbl[]存放的就是任務控制塊的首地址)和任務堆棧相聯繫(經過OS_TCB結構的OSTCBStkPtr元素指向任務堆棧的棧頂來實現)。在新建一個任務的時候,都必須新建任務控制塊置於任務控制塊鏈表中,經過OSTCBList來實現將其放於任務控制塊鏈表的開頭即新建的任務控制塊。spa

      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。io

     因爲ucos-ii爲實時系統,爲了儘可能縮短查找表所用的時間,其還定義了兩個常數數組,一個爲OSMapTbl[8]和OSUnMapTbl[256]。(我我的認爲這兩個數組的設計最爲巧妙和最有價值),經過這兩張表很方便的就能夠查詢是否有任務處於就緒態,處於就緒態的最高優先級是多少。而且將一個任務置於就緒狀態或者進行任務的調度都須要利用這兩個常數數組。List

  OSMapTbl[]表如圖1所示:定時器

 

  OSUnMapTbl[]表如圖2所示:程序

 

      D、空任務控制塊鏈表,用來管理空任務控制塊。當新建任務時,須要從該鏈表獲取一個OS_TCB, 並將其放於任務控制塊鏈表中。在這過程當中主要是經過兩個OS_TCB指針來完成,一個是OSTCBFreelist,另外一個是OSTCBList,這兩個指針始終指向鏈表的開頭。鏈表

      二、任務的建立過程

      經過函數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中。任務函數的首地址存放在任務的堆棧中。

      三、任務調度

      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) 必須保存前一任務的信息;

相關文章
相關標籤/搜索