任务就绪表:
为就绪态的任务分配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减一。