四. 就緒列表

準備運行的任務被放置於就緒列表中。就緒列表包括2 個部分:位映像組包含了優先級信息,一個表包含了所有指向就緒任務的指針。

一  優先級

顯示了優先級的位映像組。它的寬度取決於CPU_DATA 的數據類型(見CPU.H),它可以是8 位、16 位、32 位。根據處理器相應地設定。
uC/OS-III 支持多達OS_CFG_PRIO_MAX 種不同的優先級(見OS_CFG.H)。在uC/OS-III 中,數值越小優先級越高。因此優先級0是優先級最高的。優先級OS_CFG_PRIO_MAX-1 的優先級最低。uC/OS-III 將最低優先級唯一地分配給空閒任務,其它任務不允許被設置爲這個優先級。當任務準備好運行了,根據任務的優先級,位映像表中相應位就會被設置爲1。如果處理器支持位清零指令CLZ,這個指令會加快位映像表的設置過程。


OS_PRIO.C 中包含了位映像表的設置、清除、查找的相關代碼。這些函數都是uC/OS-III 的內部函數,可以用彙編語言優化。
函數 功能 
OS_PrioGetHighest() 查找最高優先級
OS_PrioInsert() 設置位映像表中相應的位
OS_PrioRemove() 清楚位映像表中相應的位

爲了確定就緒列表中優先級最高的任務,位映像表會被掃描,通過OS_PrioGetHighest()函數找到優先級最高的任務。代碼如下:

(1)OS_PrioGetHighest()函數掃描OSPrioTbl[]表直到找到非0的記錄。這個循環最終會停止,因爲總是有非0 記錄(空閒任務的存在)。
(2) 當這個表中全是0 記錄時,就會從下一個表中查找。優先級"prio"會被增加(如果表長32 位,就將prio 加上32)
(3)當找到第一個非0 位時,計算該位之前0 位的個數,返回該優先級值。如果CPU 提供清零指令,可以通過這個指令優化代碼。如果CPU 沒有這個指令,那麼這個指令就只能用C 語言模擬了。函數CPU_CntLeadZeros()統計了CPU_DATA 記錄中0 的個數(從左邊開始,以位計)。例如,假定位映像表長32 位,0xF0001234 返回的非0 位前0 位數的個數是0。0x00F01234 返回的是8。

二  就緒列表

準備好運行的任務被放到就緒列表中,如圖6-1。就緒列表是一個數組(OSRdyList[]),它一共有OS_CFG_PRIO_MAX 條記錄,記錄的數據類型爲OS_RDY_LIST(見OS.H)。就緒列表中的每條記錄都包含了三個變量.Entries 、.TailPtr 、.HeadPtr。

.Entries 中該優先級的就緒任務數。當該優先級中沒有任務就緒時,.Entries 就會被設置爲0。
.TailPtr 和.HeadPtr 用於該優先級就緒任務的建立雙向列表。.HeadPtr 指向列表的頭部,.TailPtr 指向列表的尾部。
表中的記錄跟任務的優先級有關。例如,如果一個任務的優先級是5,那麼當它就緒時會被放入OSRdyList[5]中。
表6-2 中列出了與就緒列表相關的操作函數。這些都是uC/OS-III的內部函數,用戶不能調用它們。
函數名 功能
OS_RdyListInit() 初始化就緒列表爲空
OS_RdyListInsert() 插入一個TCB 到就緒列表
OS_RdyListInsertHead() 插入一個TCB 到就緒列表的頭部
OS_RdyListInsertTail() 插入一個TCB 到就緒列表的尾部
OS_RdyListMoveHeadToTail() 將TCB 從列表的頭部移到尾部
OS_RdyListRemove() 將TCB 從就緒列表中移除
假定uC/OS-III 內部的任務都被使能。圖6-5 顯示了當OSInit()被調用後的就緒列表


Entries=1,表示有一個任務,當某個優先級中只有一個任務的時候,它的頭指針和尾指針會指向同一個TCB
uC/OS-III 允許多個任務有相同的優先級。特別的,時基任務的優先級要高於定時器任務,定時器任務的優先級需要於統計任務。

三 添加任務到就緒隊列

uC/OS-III 提供很多服務可以把任務添加到就緒列表中。最明顯的服務是OSTaskCreate(),它通常創建準備運行的任務並將任務放入就緒列表中。如圖6-6 所示,就緒列表中該優先級中已經有兩個任務了。OSTaskCreate()就會將這個任務插入到列表的未部。



(1)在調用OSTaskCreate()之前,已經有兩個任務在就緒列表中的該優先級中了。
(2)一個新的TCB 傳遞給OSTaskCreate(),然後uC/OS-III 初始化這個TCB。
(3)OSTaskCreate()調用OS_RdyListInsertTail(),OS_RdyListInsertTail()的作用是將新添加進來的TCB 鏈接到就緒隊列中對應優先級記錄(需設置四個指針,就緒列表中兩個,任務重兩個,並將記錄中的.Entries 的值加一)。OSTaskCreate()還會調用OS_PrioInsert()設置位映像表中的相應位。然而,處理OS_PrioInsert()是非常快的,它不會影響到應用的性能。當一個任務創建了一個具有相同優先級的任務,這個新任務會被添加到該優先級隊列的尾部(因爲具有相同優先級情況下,沒有理由讓新任務先運行)。然而,當一個任務創建了一個具有不同優先級的任務時,這個新的任務就會放到對應優先級列表中的首部。

四  總結

uC/OS-III 支持任意數量的優先級。然而,絕大多數系統的需求量不會超過64 種。就緒隊列包含兩個數據結構:位映像表保存了哪個優先級中有任務待運行,優先級列表中包含了這該優先級下等待運行的任務。處理器支持清零指令CLZ 會加快位映像表的掃描速度。{注意:正在運行的任務也被放在就緒列表中。}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章