任務就緒表及任務排程
任務就緒表:
為就緒態的任務分配CPU是多工作業系統的核心工作。這個工作有兩項技術:
1. 判斷哪些任務處於就緒態。
2. 進行任務排程。(任務排程就是通過一個演算法在就緒任務中確定應該馬上執行的任務)
在uCOSII中,任務就緒表就是一個位圖
OSRdyTbl [ 0 ]:D7 -D0;
OSRdyTbl [ 1 ]:D15-D8;
OSRdyTbl [ 2 ]:D23-D16;
OSRdyTbl [ 3 ]:D31-D24;
OSRdyTbl [ 4 ]:D39-D32;
OSRdyTbl [ 5 ]:D47-D40;
OSRdyTbl [ 6 ]:D55-D48;
OSRdyTbl [ 7 ]:D63-D56;
為每個任務安排了一個2進位制位,並規定該位的值為1表示對應任務處於就緒態,而該位為0表示對應任務處於非就緒態。
並定義了一個8bit的變數OSRdyGrp,該變數的各位對應OSRdyTbl陣列中的元素中是否有就緒任務。
對任務就緒表的操作
系統對任務就緒表有三個操作:登記、登出、從就緒表的就緒任務中得到最高優先順序。
1.登記:當某個任務處於就緒態時,系統將該任務登記在任務就緒表中,即在就緒表中將該任務對應位置1。
OSRdyGrp |= OSMapTbl[prio>>3];
OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07];
OSMapTbl陣列相當於一個3線8線譯碼器,為了提高查詢速度。
2.登出:當某個任務需要脫離就緒態時,系統在就緒表中將該任務的對應位置0。
if((OSRdyTbl[prio>>3]&=~OSMapTbl[prio&0x07])==0)
OSRdyGrp&=~OSMapTbl[prio>>3];
3.最高優先順序就緒任務的查詢:
y = OSUnMapTal[OSRdyGrp];//獲得優先順序的D5,D4,D3
x = OSUnMapTal[OSRdyTbl[y]];//獲得優先順序的D2,D1,D0
prio = (y<<3)+x;
或
y = OSUnMapTal[OSRdyGrp];
prio = (y<<3)+OSUnMapTal[OSRdyTbl[y]];
OSUnMapTal陣列相當於一個編碼器,這個編碼器有些特殊,它只將LSB-MSB遇到的第一個1進行編碼。
它是為了提高查詢速度定義的一個數組,有256個元素,
D0=1(2^7),D1=1(2^6),D2=1(2^5),D3=1(2^4),
D4=1(2^3),D5=1(2^2),D6=1(2^1),D7=1 (2^0)。
因為如果通過迴圈的方式查詢OSRdyGrp從低位到高位的第一個1,那麼每位為1查詢的時間不同,而且時間不確定,通過陣列查詢每位為1查詢的時間相同且速度塊。
任務排程——任務排程器:
1. 任務級排程器OSSched();
2. 中斷級排程器OSIntExt()。
每時每刻讓優先順序最高的就緒任務處於執行態。具體做法為:在系統或使用者任務呼叫系統函式及執行中斷服務程式結束時呼叫排程器,以確定應該執行的任務並執行它。
排程器的主要任務
1)在任務就緒表中查詢具有最高優先順序的就緒任務
2)任務切換
任務切換分為兩個步驟:第一步獲得待執行任務的TCB指標,第二步進行斷點資料的切換。
void OSSched(void)
{
#if OS_CRITICAL_METHOD==3
OS_CPU_SRcpu_sr;
#endif
INT8U y;
OS_ENTER_CRITICAL();
if((OSLockNesting|OSIntNesting)==0)
//排程器被鎖上的次數不為0,而且不是中斷服務程式呼叫排程器
{
y=OSUnMapTbl[OSRdyGrp];
OSPrioHighRdy=(y<<3)+OSUnMapTal[OSRdyTbl[y]];
//獲取就緒表中的最高優先順序任務
if(OSPrioHighRdy!=OSPrioCur)
//判斷最高優先順序就緒任務不是當前的任務
{
OSTCBHighRdy=OSTCBPrioTbl[OSPrioHighRdy];
//得到任務TCB的指標
OSCtxSwCtr++;//統計任務切換次數的計數器+1
OS_TASK_SW();//巨集,任務切換
}
}
OS_EXIT_CRITICAL();
}
uCOSII允許應用程式通過函式:
OSSchedLock()和OSSchedUnlock()
給排程器上鎖和解鎖。上鎖OSLockNesting加一,解鎖OSLockNesting減一。