uC/OS-II任務調度之就緒表及最高優先級任務判定算法

uC/OS-II是Jean J. Labrosse設計的完整的、可移植、可固化、可裁剪的搶佔式實時多任務內核,絕大部分代碼都是用標準的C語言編寫的,開源、規模不大,比較適合初次接觸嵌入式操作系統的人員學習和使用。2000年7月,uC/OS-II在一個航空項目中得到了美國聯邦航空管理局(FAA)對用於商用飛機的、符合RTCA DO-178B標準的認證。


(一)在就緒表(Reday List)中作標記

每個任務的就緒標記都會被放入就緒表中,與就緒表相關的變量有兩個,即OSRdyGrp和OSRdyTbl[]。

OSRdyGrp定位的是任務所在的行,OSRdyTbl[]定位的是任務所在的列。

OSRdyGrp的每一位都分別對應一個行(行號從0到7),OSRdyTbl[i]的每一位分別對應第i行的一個列(列號從0到7)。


1、OSRdyGrp

就緒任務所在的組,其定義位於UCOS_II.H,是一個8位無符號整型。OSRdyGrp哪個位爲1就說明哪一行有就就緒的任務,源代碼中的定義如下:

OS_EXT  INT8U        OSRdyGrp;                        /* Ready list group                              */

2、OSRdyTbl[]

就緒表,其定義位於UCOS_II.H,是一個一維數組。源代碼中的定義如下:

#define  OS_RDY_TBL_SIZE   ((OS_LOWEST_PRIO) / 8 + 1)   /* Size of ready table                         */
OS_EXT  INT8U        OSRdyTbl[OS_RDY_TBL_SIZE];       /* Table of tasks which are ready to run         */

上面代碼中的OS_LOWEST_PRIO的宏定義位於OS_CFG.H,對於uC/OS_II,該值最大爲63。源代碼中的定義如下:

#define OS_LOWEST_PRIO           60    /* Defines the lowest priority that can be assigned ...         */
                                       /* ... MUST NEVER be higher than 63!                            */

3、OSMapTbl[]

映射表,其定義位於OS_CORE.C,是一個一維數組,包含8個元素。源代碼中的定義如下:

/*
*********************************************************************************************************
*                              MAPPING TABLE TO MAP BIT POSITION TO BIT MASK
*
* Note: Index into table is desired bit position, 0..7
*       Indexed value corresponds to bit mask
*********************************************************************************************************
*/

INT8U const OSMapTbl[]   = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};


以下代碼用於將任務放入就緒表,prio爲任務的優先級。

OSRdyGrp            |= OSMapTbl[prio >> 3]; 
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];

舉例:假如只有一個任務,該任務的優先級prio = 11 = 00 001 011,高三位爲001,低三位爲011,則

OSRdyGrp = OSMapTbl[prio >> 3] = OSMapTbl[1] = 0x02 = 0000 0010

OSRdyTbl[prio >> 3] = OSRdyTbl[1] = OSMapTbl[3] = 0x08 = 0000 1000

這樣,向任務就緒表的第1行第3列寫1,即完成了該任務的就緒標記寫入。


(二)找出進入就緒狀態的優先級最高的任務

4、OSUnMapTbl[]

優先級判定表,其定義位於OS_CORE.C,是一個一維數組,包含256個元素。源代碼中的定義如下:

/*
*********************************************************************************************************
*                                       PRIORITY RESOLUTION TABLE
*
* Note: Index into table is bit pattern to resolve highest priority
*       Indexed value corresponds to highest priority bit position (i.e. 0..7)
*********************************************************************************************************
*/

INT8U const OSUnMapTbl[] = {
    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};

算法如下:

y    = OSUnMapTbl[OSRdyGrp]; 
x    = OSUnMapTbl[OSRdyTbl[y]]; 
prio = (y << 3) + x; 


舉例:假設有3個任務,優先級分別爲10、21、53

對於優先級爲10的任務:

prio = 00 001 010

OSRdyGrp = OSMapTbl[prio >> 3] = OSMapTbl[1] = 0x02 = 0000 0010

OSRdyTbl[prio >> 3] = OSRdyTbl[1] = OSMapTbl[2] = 0x04 = 0000 0100

對於優先級爲21的任務:

prio = 00 010 101

OSRdyGrp = OSMapTbl[prio >> 3] = OSMapTbl[2] = 0x04 = 0000 0100

OSRdyTbl[prio >> 3] = OSRdyTbl[2] = OSMapTbl[5] = 0x04 = 0010 0000

對於優先級爲53的任務:

prio = 00 110 101

OSRdyGrp = OSMapTbl[prio >> 3] = OSMapTbl[6] = 0x40 = 0100 0000

OSRdyTbl[prio >> 3] = OSRdyTbl[6] = OSMapTbl[5] = 0x04 = 0010 0000

最後OSRdyGrp的值就是將所有的OSMapTbl[prio>>3]進行按位或運算:

OSRdyGrp = 0000 0010 | 0000 0100 | 0100 0000 = 0100 0110 = 70

同理,OSRdyTbl[1] = 0000 0100,OSRdyTbl[2] = 0010 0000,OSRdyTbl[6] = 0010 0000


然後,根據優先級判定表OSUnMapTbl[],可以確定優先級最高的任務

OSRdyGrp = 70

y = OSUnMapTbl[OSRdyGrp] = OSUnMapTbl[70] = 1

x = OSUnMapTbl[OSRdyTbl[y]] = OSUnMapTbl[OSRdyTbl[1]] = OSUnMapTbl[4] = 2

prio = (y << 3) + x = 10,即處於就緒狀態的優先級最高的任務是優先級爲10的任務。


這樣做的好處其實就是以空間來換取時間,提高程序執行的效率。如果我們自己設計,首先想到的算法可能就是定義一個一維數組OSRdy[],包含64個元素,對應64個任務,當某個任務處於就緒狀態時,就將相應的元素置1,比如優先級53的任務就緒,那麼就令OSRdy[53] = 1,這樣一來,通過查找法可以找到位於就緒狀態的優先級最高的任務,其弊端就是當處於就緒狀態的優先級最高的任務比較靠後時(比如優先級爲63),查找所消耗的時間較多,效率相對較低,而uC/OS-II中採用的算法只用幾行代碼就可以快速找到優先級最高的任務,且對不同的任務所消耗的時間基本一致、相對公平。


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