1. 程式人生 > >uC/OS-II任務排程之就緒表及最高優先順序任務判定演算法

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

相關推薦

uC/OS-II任務排程就緒最高優先順序任務判定演算法

uC/OS-II是Jean J. Labrosse設計的完整的、可移植、可固化、可裁剪的搶佔式實時多工核心,絕大部分程式碼都是用標準的C語言編寫的,開源、規模不大,比較適合初次接觸嵌入式作業系統的人員

uC/OS-II 學習筆記:訊息佇列

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UCOS II怎麼查詢當前就緒中,優先順序最高任務

uCOS-II為了保證CPU總是執行優先順序最高的任務,每當任務狀態發生變化時,就需要判斷當前任務是否為最高優先順序,不是的話就需要進行上下文切換。如何在需要進行任務優先順序比較時,快速的將就緒態任務中優先順序最高的讀出。一種最簡單的資料結構就是定義一個unsi

uC/OS II 函式說明 –OS_TCBInit()

TCB初始化函式,被OSTaskCreate()與OSTaskCreateExt()呼叫,需要注意的是,這個函式是對內的,即此函式可以被uC/OS II呼叫,使用者應用程式不可以直接呼叫此函式。OSTcbInit()函式的引數是與OSTaskCreateExt()的引數對應的

uC/OS II 函式說明 –OSTaskCreate()與OSTaskCreateExt()

#if OS_ARG_CHK_EN > 0    if (prio > OS_LOWEST_PRIO) {             /* 引數檢查,優先順序是否處於允許優先順序之內     */        return (OS_PRIO_INVALID);    }#endif    OS_E

uC/OS-II 學習筆記:訊息郵箱

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

UC/OS-II學習筆記訊息佇列使用

對訊息佇列的學習理解有點難,對技術來說,一本好的書一般是原理和例子相結合的,可惜我找到的很少。書上說訊息佇列實際上是多個郵箱組成的陣列,是一個列表。這個陣列其實是個指標陣列,裡面每個指標可以指向不同型別的變數,通過傳遞一個個指標,我們可以做到傳遞指標所指向的一個個變數。(順便複習下,一個郵箱只能傳遞一個指標,

uC/OS II 函式說明與訊號量操作相關的六個函式

    if (OSIntNesting > 0) {                           /* ISR中,不允許此操作                           */        *err = OS_ERR_PEND_ISR;                        

uc/os-ii任務排程的鎖定與解鎖

排程器上鎖函式OSSchedlock()的功能是用於禁止任務排程,使任務保持對CPU的控制權。排程器開鎖函式OSSchedUnlock()的功能是解除對任務排程的禁止。 排程器上鎖和開鎖的實現原理是:對全域性變數鎖定巢狀計數器OSLockNesting進行操作

uC/OS-II任務排程中判斷最高優先順序

一、任務優先順序的表示    uC/OS-II中,規定最多可以有64個任務。每個任務的優先順序不能相同,因此,優先順序為0~63.數字越小,優先順序越高,那麼0就是最高優先順序,63就是最低優先順序。系統保留了優先順序最高及最低的各4個,因此使用者不能使用這8個優先順序作為自己的任務的優先順序。巨集OS_L

uc/os-ii任務排程(二)

任務排程關鍵是任務執行環境的切換。任務執行環境包括以下: 1. 程式的斷點地址(PC) 2. 程式狀態字暫存器(xPSR) 3. 通用暫存器內容 4. 任務堆疊指標(SP) 其中1、2、3儲存在任務堆疊中,4儲存在任務的任務控制塊中。 程式切換的關鍵

UC/OS-II 任務的狀態

uc/os是一個搶佔式多工的實時作業系統,每個任務都有各自的狀態,並且狀態之間都有一定的轉換關係。寫下此文以作記錄及幫助自己理清關係。 在uc/os-ii中,任務的狀態有5種:睡眠態、就緒態、執行態、等待態及中斷服務態。通過下圖可以有一個大致的認知: 最

uC/OS-II任務同步與通訊

在多工合作過程中的,作業系統應解決兩個問題:一是各任務之間應具有一種互斥關係,即對於某個共享資源的共享,如果一個任務正在使用,則其他任務只能等待,等到該任務釋放該資源以後,等待的任務之一才能使用它;二是相關的任務在執行上要有先後次序,一個任務要等其夥伴發來通知或建立了某個條件

uc/os-ii刪除任務

uC/OS-II中與刪除任務相關的函式有兩個,刪除任務函式OSTaskDel() 和請求刪除任務函式OSTaskDelReq() 。 刪除任務函式原始碼如下,主要工作: 判斷引數的有效性 把要刪除的任務從任務就緒表中刪除 使被刪除的任務不等待延時期滿 ,

uC/OS-II任務機制理解

        半年前接觸的uC/OS,看了兩個月之後又因為其他的事把他放下了。現在因為專案需要又把它重拾起來。         uC/OS----Micro Controller OS微控制器作業系

任務就緒任務排程

任務就緒表: 為就緒態的任務分配CPU是多工作業系統的核心工作。這個工作有兩項技術: 1. 判斷哪些任務處於就緒態。 2. 進行任務排程。(任務排程就是通過一個演算法在就緒任務中確定應該馬上執行的任務) 在uCOSII中,任務就緒表就是一個位圖

嵌入式實時作業系統uc-os-ii原理應用 第三章 uc/os-ii中的任務

3.1-3.4.3  印象比較深的點在作業系統中程式叫做程序或執行緒。系統任務:空閒任務和統計任務。不同處理器,堆疊的增長方向不同。實時作業系統,時間操作必須為常量,所以不能用for,配合break或continue。不然每個任務執行時間不同。

經典:uC/OS-II系統的學習教程(三)

核心結構 本章給出μC/OS-Ⅱ的主要結構概貌。讀者將學習以下一些內容;μC/OS-Ⅱ是怎樣處理臨界段程式碼的;什麼是任務,怎樣把使用者的任務交給μC/OS-Ⅱ;任務是怎樣排程的;應用程式CPU的利用率是多少,μC/OS-Ⅱ是怎樣知道的;怎樣寫中斷服務子程式;什麼是時鐘節拍,

Spring:任務排程task:scheduler與task:executor配置的詳解

其實就是Spring定時器中配置檔案中一些配置資訊,由於筆者自己是頭一次使用,有些配置詳細不太明白,隨即研究了一番,於是想記錄一下,有需要的小夥伴可以參考,也方便日後自己查閱。 首先,建立一個僅僅包含定時器配置的Spring配置檔案:spring-timer.xml。以下均為配置資訊:1、在配置檔案