uc/os -ii 核心算法分析

μC/OS-Ⅱ是一種免費公開源代碼、結構小巧、具有可剝奪實時內核的實時操作系統。其 內核提供任務調度與管理、時間管理、任務間同步與通信、內存管理和中斷服務等功能。適合小型控制系統,具有執行效率高、佔用空間小、實時性能優良和可擴展 性強等特點,最小內核可編譯至2KB。μC/OS-Ⅱ爲何如此高效呢?我們從它的核心算法——任務調度算法開始分析。
2.1任務調度算法分析
        操作系統的實時性主要體現在:當優先級高的任務要求工作時,操作系統要以儘快的時間將此任務調度到CPU執行。這裏所花費的時間主要包括兩部分:查找最高 優先級任務和任務上下文切換。其中,任務上下文切換時間是和處理器相關的,操作系統無法控制。我們主要分析uC/OS-ii如何查找最高優先級任務的。
          因爲任務較少,uC/OS-II採用單一優先級,這爲算法的實現提供了很大的方便在uC/OS-II中,優先級可以作爲任務的標識(當然要在任務存在的情況下,是通過一個指針數組實現的)來用。
            調度算法主要基於分級查詢。考慮到任務數目<64,可以用6bit來表示,分爲高3位和低三位。uC/OS-II將優先級進行分組,按高三位進行 分組,可得8個(最多)優先級數組(000-111);每個優先級的在數組中的位置由其低三位表示。在源碼中,高三位用帶Y後綴的變量表示,而低三位用帶 X後綴的變量表示。這樣建立了1個變量OSRdyGrp(INT8U,8bit,每個bit代表一組)和1個數組OSRdyTbl[8](INT8U,每 組8bit,每個bit代表一個優先級)。這樣形成了的二級查詢,先選組,再選組內偏移。
        其中,OSRdyGrp每一bit置1,表示該組有任務就緒。(第0~7組)。其示意圖見下圖:

我 們舉一個例子,看一下如果優先級爲22的任務就緒,我們如何對優先級數組進行操作。用二進制表示爲0b00010110,其高3位爲010,爲2,則將 第2組,也就是OSRdyGrp的第2位置1。其低3位爲110,爲6,則將其OSRdyTbl[2]的第6位置1。編程實現時,可以通過對1進行移位, 再進行 或 操作來實現。但考慮到移位時間不確定,uC/OS-II選擇建立了一個表OSMapTbl[8],如下。
表 T3.1 OSMapTbl[]的值

Index        Bit Mask (Binary)
0        00000001
1        00000010
2        00000100
3        00001000
4        00010000
5        00100000
6        01000000
7        10000000
這樣,當一個任務就緒時,我們這樣處理。其中Prio是任務的優先級。
程序清單 L3.5 使任務進入就緒態
OSRdyGrp            |= OSMapTbl[prio >> 3];
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];
而當任務被掛起或刪除時,我們這樣處理:
程序清單 L3.6 從就緒表中刪除一個任務
if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0)
    OSRdyGrp &= ~OSMapTbl[prio >> 3];
表建立了,如何查詢最高優先級呢?這是很關鍵的。因爲優先級的值越小,優先級越高,我們只需從OSRdyGrp中找到最低位置1的的那一組,再從該組中,查找最低位置1的位置,組合一下,就得到了最高的優先級。
同樣,這可以通過一個while循環進行判斷,但是,時間也是不確定的。所以,uC/OS-II又建立了一張表OSUnMapTbl,這張表有點大,其下標值範圍爲0x00-0xff,值域爲0-7。
這樣,其查詢流程爲:
程序清單 L3.7 找出進入就緒態的優先級最高的任務
y    = OSUnMapTbl[OSRdyGrp];
x    = OSUnMapTbl[OSRdyTbl[y]];
prio = (y << 3) + x;

2.2事件處理算法分析
在uC/OS-II中,事件可以是信號量、郵箱或者消息隊列等,並用統一的結構體OS_EVENT表示。
我們先看一下OS_EVENT的組成:
typedef struct {
INT8U           OSEventType;                 
INT8U    OSEventGrp;                    
INT16U          OSEventCnt;                    
void           *OSEventPtr;                  
INT8U    OSEventTbl[OS_EVENT_TBL_SIZE];
} OS_EVENT;
        注意其中兩個變量:OSEventGrp和OSEventTbl[],是不是覺得有點象OSRdyGrp和OSRdyTbl[]。那它們的處理算法是不是 也一樣呢?你猜對了,這裏關於事件的各種操作(如pend、post、timeout、wait等)的算法和任務調度算法如出一轍。當然也用到了 OSUnMapTb[]和OSMapTbl[]。只是任務就緒時(等待CPU時)插入就緒表,而當任務需要等待事件時要插入EVENT等待列表,反之亦 同。
2.3 小結
        這兩個算法(1種算法)是os_core.c中最主要的算法。此算法執行時間恆定,不隨任務數目的多少變化(但不能超過64個任務),保證了其實時性。這 裏,順便對uC/OS-ii的設計哲學進行臆測:那就是“以空間換時間”,也就是表格table (array)。這可以從uC/OS-II中存在衆多的全局變量,如OSEventTabl[],OSRdyTbl[],OSTCBTbl[](這樣避免 了動態初始化)看出,也可以從上面介紹的任務調度算法中看出(核心數據結構爲數組,並建立了兩張表OSUnMapTbl和OSMapTbl)。

 

來源:http://www.yuanma.org/data/2007/0207/article_2249.htm

發佈了22 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章