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中採用的算法只用幾行代碼就可以快速找到優先級最高的任務,且對不同的任務所消耗的時間基本一致、相對公平。