Nucleus PLUS任務排程

yangzhao0001發表於2015-09-14

概述

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

  1. 若任務的優先順序為Tc_priority,     
  2. 該任務的子優先順序掩碼為:tc_sub_priority=1<<(tc_priority&7)。     
  3. 該任務的優先順序組掩碼為: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,所以有:

  1. TCD_Lowest_Set_Bit[1]= 0,     
  2. TCD_Lowest_Set_Bit[3]= 0,     
  3. TCD_Lowest_Set_Bit[5]= 0,     
  4. TCD_Lowest_Set_Bit[7]= 0,     
  5. ...,     
  6. TCD_Lowest_Set_Bit[253]= 0,     
  7. TCD_Lowest_Set_Bit[255]= 0。    

 

2.4 任務建立和優先順序管理的基本過程

任務優先順序管理全域性變數

  1. UNSIGNED        TCD_Priority_Groups;     
  2. DATA_ELEMENT    TCD_Sub_Priority_Groups[TC_MAX_GROUPS];     
  3. UNSIGNED_CHAR  TCD_Lowest_Set_Bit[256] = {0,     
  4.  0102010301020104010201030,     
  5.  1020105010201030102010401,     
  6.  0201030102010601020103010,     
  7.  2010401020103010201050102,     
  8.  0103010201040102010301020,     
  9.  1070102010301020104010201,     
  10.  0301020105010201030102010,     
  11.  4010201030102010601020103,     
  12.  0102010401020103010201050,     
  13.  1020103010201040102010301,     
  14.  02010};     
  15. INT             TCD_Highest_Priority;//就緒狀態任務的最高優先順序    
i.建立一個task時(tcc.c)--TCC_Create_Task funtion

  1. extern UNSIGNED         TCD_Priority_Groups;     
  2. extern DATA_ELEMENT     TCD_Sub_Priority_Groups[TC_MAX_GROUPS];     
  3. extern UNSIGNED_CHAR    TCD_Lowest_Set_Bit[];     
  4. extern INT              TCD_Highest_Priority;        
  5. task -> tc_priority = priority;     
  6. task -> tc_priority_head = &(TCD_Priority_List[priority]);     
  7. task -> tc_sub_priority = (DATA_ELEMENT) (1 << (priority & 7));//組內子優先順序計算,0-7     
  8. priority =  priority >> 3;//優先順序組計算,有32個組     
  9. task -> tc_priority_group = ((UNSIGNED) 1) << priority;//優先順序組響應組標示位置1     
  10. task -> tc_sub_priority_ptr = &(TCD_Sub_Priority_Groups[priority]);//指向子優先順序起始    

ii. 恢復執行一個task時(tcc.c)--TCC_Resume_Task fuction

  1. TCD_Priority_Groups = TCD_Priority_Groups | (task -> tc_priority_group);  
  2. //組號儲存到全域性變數        
  3. *(task -> tc_sub_priority_ptr) = (*(task -> tc_sub_priority_ptr)) | task -> tc_sub_priority;  
  4. //組內值儲存到全域性變數     

iii.獲取當前最高優先順序(tcc.c)

  1. if (TCD_Priority_Groups & TC_HIGHEST_MASK)     
  2.       index =  0;     
  3. else if (TCD_Priority_Groups & TC_NEXT_HIGHEST_MASK)     
  4.   index =  8;     
  5. else if (TCD_Priority_Groups & TC_NEXT_LOWEST_MASK)     
  6.   index =  16;     
  7. else    
  8.   index =  24;     
  9.   index =  index + TCD_Lowest_Set_Bit[(INT)((TCD_Priority_Groups >> index) & TC_HIGHEST_MASK)];//獲取組號中1的最低排位,取值範圍0~31     
  10.   temp =  TCD_Sub_Priority_Groups[index];//與priority_group對應,有32個Sub_Priority_Groups,通過index查詢到相應的Sub_Priority_Groups     
  11.   TCD_Highest_Priority = (index << 3) + TCD_Lowest_Set_Bit[temp];//獲取到實際的最高優先順序    
獲取到實際的最高優先順序後,將最高優先順序的任務掛入Tcd_priority_list[]、完成排程後,該任務位會被清空,接著再次迴圈獲取下一個任務優先順序。

相關文章