uC/OS-II中优先级机制分析

来源:互联网 发布:比较好玩的java游戏 编辑:程序博客网 时间:2024/06/03 14:36


在网上找到的~感觉总结的非常好~贴过来保存下~源地址:http://peacemind.blog.hexun.com/15156734_d.html


uC/OS-II中共有64个优先级,0优先级最高,63优先级最低。每个优先级只能对应到一个任务,也就是说在uC/OS-II不支持具有相同优先级的任务,所以只能创建64个任务,而用户只能创建56个任务,有一个优先级最低的空闲任务,在没有用户任务运行的时候运行。 
uC/OS-II支持不同优先级间的任务调度,通过任务各自对应的优先级状态,快速地由OSTCBPrioTbl[OSPrioHighRdy]OSPrioHighRdy用来记录当前任务中最高优先级值)指针的指向切换到期望的TCB 来完成调度。这种调度与uC/OS-IIOSTCBList 数据结构紧密相关,其数据结构如图所示。 


这是一个双向线性链表结构,任务调度是从线性链表上的一个结点一个TCB 控制块切换到从链表上的另一个结点,而不同的结点对应着不同的优先级,这样来完成不同优先级的任务调度。 



我们知道每个任务都有自己的优先级,不能和其他任务优先级相同。每个任务的就绪态标志都放入就绪表中的,就绪表中有两个变量OSRdyGrpReady list group)和OSRdyTbl[]Table of tasks which are ready to run)。在OSRdyGrp中,任务按优先级分组,8个任务为一组。OSRdyGrp中的每一位表示8组任务中每一组中是否有进入就绪态的任务。任务进入就绪态时,就绪表OSRdyTbl[]中的相应元素的相应位也置位。就绪表OSRdyTbl[]数组的大小取决于OS_LOWEST_PRIO(见文件OS_cfg.h)。 
为确定下次该哪个优先级的任务运行了,内核调度器总是将OS_LOWEST_PRIO在就绪表中相应字节的相应位置1OSRdyGrpOSRdyTbl[]的关系见上图,是按以下规则给出的: 
OSRdyTbl[0]中的任何一位是1时,OSRdyGrp的第0位置1, 
OSRdyTbl[1]中的任何一位是1时,OSRdyGrp的第1位置1, 
OSRdyTbl[2]中的任何一位是1时,OSRdyGrp的第2位置1, 
OSRdyTbl[3]中的任何一位是1时,OSRdyGrp的第3位置1, 
OSRdyTbl[4]中的任何一位是1时,OSRdyGrp的第4位置1, 
OSRdyTbl[5]中的任何一位是1时,OSRdyGrp的第5位置1, 
OSRdyTbl[6]中的任何一位是1时,OSRdyGrp的第6位置1, 
OSRdyTbl[7]中的任何一位是1时,OSRdyGrp的第7位置1。 
下面的程序清单中代码用于将任务放入就绪表。Prio是任务的优先级。使任务进入就绪态。 

/*这行代码功能是找到列把列上的值置为1。不妨假设prio的值为13, 即优先级为13. prio>>3 右移3位后值为1, 可以查OSMapTbl表找出 OSMapTbl[1] 的值为 0000 0010. 再用0000 0010  OSRdyGrp 进行或运算。*/ 
OSRdyGrp |= OSMapTbl[prio >> 3]; 
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07]; 

任务优先级的低三位用于确定是在OSRdyTbl[prio >> 3]数组的第几位。 OSMapTbl[]是在ROM中的(见文件OS_core.c)屏蔽字,用于限制OSRdyTbl[]数组的元素下标在07之间(或者我们可以这样理解:任务的优先级在[0,范围,共分为8组,每组8个任务,用6位二进制可以表示,其中任务优先级的高三位理解为优先级所在的组(prio >> 3),低三位理解为所在组中的偏移量(prio & 0x07)),见下表。

查看更多精彩图片

如果一个任务被删除了,则用如下程序清单中的代码做求反处理。从就绪表中删除一个任务。 

if ((OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07]) == 0) 
     OSRdyGrp &= ~OSMapTbl[prio >> 3]; 

以上代码将就绪任务表数组OSRdyTbl[]中相应元素的相应位清零,而对于OSRdyGrp,只有当被删除任务所在任务组中全组任务一个都没有进入就绪态时,才将相应位清零。也就是说OSRdyTbl[prio>>3]所有的位都是零时,OSRdyGrp的相应位才清零。为了找到进入就绪态的优先级最高的任务,并不需要从OSRdyTbl[0]开始扫描整个就绪任务表,只需要查另外一张表,即优先级判定表 OSUnMapTbl [256](见文件OS_core.c)OSRdyTbl[]中每个字节的8位代表这一组的8个任务哪些进入就绪态,且低位的优先级高于高位。利用OSRdyGrp查找OSUnMapTbl表可以得到就绪态中优先级最高任务所在的组,利用OSRdyTbl[OSUnMapTbl[OSRdyGrp]] 查找OSUnMapTbl表可以得到就绪态中优先级最高任务所在组中的偏移值,计算后就可以获得就绪态中最高优先级是多少,然后,通过OSTCBPrioTbl[prio]就可以得到就绪态的优先级最高的任务。代码如下: 

y    = OSUnMapTbl[OSRdyGrp]; 
x    = OSUnMapTbl[OSRdyTbl[y]]; 
prio = (y << 3) + x;; 
ptcb =OSTCBPrioTbl[prio];       /* Point to this task's OS_TCB */