標籤:rtos nucleus 任務調度 嵌入式
概述
Nucleus Plus核心(Kernel)的主要目的是管理即時任務的競爭運行(共用CPU),為應用提供各種便利,快速響應外來事件。Nucleus Plus的系統結構1所示,可以看出線程式控制制是整個核心的核心,通過郵箱、隊列、管道來實現任務之間的通訊,通過訊號量、事件組和訊號實現任務間的同步。
線程式控制制組件用來管理即時任務和進階中斷服務的執行,它是Nucleus 嵌入式即時作業系統最核心的部分。為了控制執行過程,任務通常被分配一個優先順序。任務優先順序的範圍從0到255,優先順序0的優先權最高。除非搶佔標示位被置為無效,否則低優先順序的任務將被高優先順序就緒的任務搶佔。為保證對外來事件的即時性響應,Nucleus設計了進階中斷服務HISR,它的優先順序範圍從0到2,其中優先順序0的層級最高。
任務調度線程就負責搶佔式即時任務和HISR的調度管理。每個使用者應用由多個工作群組成,一個任務就是具有特定目的的半獨立程式片段,任務處於五種狀態之一--運行、就緒、掛起、終止、完成,如表1所示。任務具有不同的優先順序,高優先順序任務能夠搶佔低優先順序任務,同優先順序任務按照進入”就緒狀態“的順序調度,優先順序從0-255遞減。
表1 Nucleus任務的五種狀態
|
狀態意義 |
運行Executing |
任務當前正在被CPU執行。 |
就緒Ready |
任務就緒,但是另一個任務當前正在運行。 |
掛起Suspended |
任務因為服務等待需求而體眠。當需求滿足時,任務變為就緒狀態。預設情況下,新建立的任務都處於 |
終止Terminated |
任務被終止。當任務處於這種狀態時,它將不再執行直到它被複位。 |
完成Finished |
任務完成了.從入口函數中退出。任務處於這種狀態時,它將不再執行直到受到複位。 |
(一)任務調度演算法
Nucleus發送器用來決定是否要進行任務切換,如果需要切換的話,切換到哪個進程等。Nucleus即時作業系統的任務調度演算法非常簡單,它包括時間片輪轉演算法和輪詢演算法。
時間片輪轉演算法是將相同優先順序的任務都分配相同的時間片,當時間片用完後再轉到下一個任務,輪流執行直到這個優先順序的所有任務全部執行完畢,然後再轉到下一個優先順序。輪詢演算法是在本優先順序內的所有任務按照就緒時間的先後 順序執行,當這個優先順序的全部任務都執行完畢後,再執行下一個優先順序的任務。
再者,Nucleus即時作業系統具有可搶佔性,進程調度的依據就是按照優先順序從高到低順序進行調度。當低優先順序任務在運行時,高優先順序任務就緒準備執行時則會搶佔執行,迫使低優先順序任務掛起。
Nucleus的調度時機包括:
(1)進程狀態轉換的時刻,即進程終止、進程睡眠;
(2)可運行隊列中新增加一個進程時;
(3)當前進程的時間片用完;
(4)進程從系統調用返回到使用者態;
(5)核心處理完中斷後,進程返回到使用者態。
(二)Nucleus PLUS任務管理1,主要任務控制結構
Nucleus PLUS每一個任務都有一個控制結構體稱為線程式控制制塊Thread Control Block(TCB),任務支援動態建立和刪除,TC通過一個雙向鏈表TCD_Created_Tasks_List管理所有的任務,全域變數TCD_Total_Tasks表示已建立的總任務數。
TCD_Priority_List是一個大小為256的TCB指標數組TC_TCB (*TCD_Priority_List)[256](數組大小與Nucleus PLUS優先順序數相同),數組元素按任務優先順序索引。數組中的每個元素都是某個優先順序就緒任務鏈表的頭。若某元素為空白則表明那個優先順序沒有就緒任務。 對於每個優先順序的就緒工作清單,TCB是以雙向列表的形式儲存。即Nucleus PLUS維護一個指標數組來調度不同優先順序的任務鏈表。
圖2 TCD_Priority_List
2,任務優先順序管理
Nucleus在進行任務切換時需要計算最高優先順序,為了快速的計算就緒任務中最高的優先順序,Nucleus PLUS引入了一種優先順序分組+尋找表機制。
2.1 TCD_Priority_Groups
任務的優先順序從0到255,0的優先順序別最高,255的優先順序別最低。256個優先順序分成32組,每組對應8個層級。例如第0組對應優先順序0~7、第1組對應 8~15、...。用32位整型變數TCD_Priority_Groups的每一位標示優先順序組是否有任務進入就緒狀態,某位為1表示改組至少有一個任務就緒。
圖3 TCD_Priority_Groups
2.2 TCD_Sub_Priority_Groups[]
子優先順序數組TCD_Sub_Priority_Groups[32]標示一個組內具體的8個優先順序,數組元素為8位整型,每一位對應組內一個優先順序。如TCD_Sub_Priority_Groups[0]表示第0組(優先順序0-7)任務的就緒狀態,第0位為1表明優先順序0的任務就緒、第7位為1表明優先順序7的任務就緒。
圖4 TCD_Sub_Priority_Groups
若任務的優先順序為Tc_priority, 該任務的子優先順序掩碼為:tc_sub_priority=1<<(tc_priority&7)。 該任務的優先順序組掩碼為:tc_priority_group=1<<((tc_priority)>>3)。
2.3 TCD_Lowest_Set_Bit[]
TCD_Lowest_Set_Bit[]是一個尋找表(元素預先已計算出),該表是8位整型資料的序號和資料8個位中第一個為1的位的位置(從高往底數)的,例如TCD_Lowest_Set_Bit[n]=value,n指8位整型數的值(就是序號),value指的是8個位中第一個為1的位置(從低往高數)。如Unsigned Char 7的二進位是0000 0111,第一個為1的位位0,value=0,TCD_Lowest_Set_Bit[7] = 0。
如此便可以求得表TCD_Lowest_Set_Bit[256]。舉例,8位整型數中位0為1的資料包括1、3、5、7、9、11、13、15,...,253,255,所以有:
TCD_Lowest_Set_Bit[1]= 0, TCD_Lowest_Set_Bit[3]= 0, TCD_Lowest_Set_Bit[5]= 0, TCD_Lowest_Set_Bit[7]= 0, ..., TCD_Lowest_Set_Bit[253]= 0, TCD_Lowest_Set_Bit[255]= 0。
2.4 任務建立和優先順序管理的基本過程
任務優先順序管理全域變數
UNSIGNED TCD_Priority_Groups; DATA_ELEMENT TCD_Sub_Priority_Groups[TC_MAX_GROUPS]; UNSIGNED_CHAR TCD_Lowest_Set_Bit[256] = {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}; INT TCD_Highest_Priority;//就緒狀態任務的最高優先順序 i.建立一個task時(tcc.c)--TCC_Create_Task funtion
extern UNSIGNED TCD_Priority_Groups; extern DATA_ELEMENT TCD_Sub_Priority_Groups[TC_MAX_GROUPS]; extern UNSIGNED_CHAR TCD_Lowest_Set_Bit[]; extern INT TCD_Highest_Priority; task -> tc_priority = priority; task -> tc_priority_head = &(TCD_Priority_List[priority]); task -> tc_sub_priority = (DATA_ELEMENT) (1 << (priority & 7));//組內子優先順序計算,0-7 priority = priority >> 3;//優先順序組計算,有32個組 task -> tc_priority_group = ((UNSIGNED) 1) << priority;//優先順序組回應群組標示位置1 task -> tc_sub_priority_ptr = &(TCD_Sub_Priority_Groups[priority]);//指向子優先順序起始
ii. 恢複運行一個task時(tcc.c)--TCC_Resume_Task fuction
TCD_Priority_Groups = TCD_Priority_Groups | (task -> tc_priority_group);//組號儲存到全域變數 *(task -> tc_sub_priority_ptr) = (*(task -> tc_sub_priority_ptr)) | task -> tc_sub_priority;//組內值儲存到全域變數
iii.擷取當前最高優先順序(tcc.c)
if (TCD_Priority_Groups & TC_HIGHEST_MASK) index = 0; else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK) index = 8; else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK) index = 16; else index = 24; index = index + TCD_Lowest_Set_Bit[(INT)((TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)];//擷取組號中1的最低排位,取值範圍0~31 temp = TCD_Sub_Priority_Groups[index];//與priority_group對應,有32個Sub_Priority_Groups,通過index尋找到相應的Sub_Priority_Groups TCD_Highest_Priority = (index << 3) + TCD_Lowest_Set_Bit[temp];//擷取到實際的最高優先順序
擷取到實際的最高優先順序後,將最高優先順序的任務掛入Tcd_priority_list[]、完成調度後,該任務位會被清空,接著再次迴圈擷取下一個任務優先順序。