uC/OS-II学习笔记(2012.12.11)任务就绪表

来源:互联网 发布:python 字符串转日期 编辑:程序博客网 时间:2024/05/24 03:20

    uC/OS-II总是在已就绪的任务中选择一个任务来运行。为了了解系统中的任务哪些是就绪任务,uC/OS-II在系统初始化时间里了一个供就绪任务登记的表,整个表就叫做就绪任务表。

    1).8x8矩阵

    Jean J.Labrosse 在设计的时候,因为uc/os中每个任务的优先级都是不同的,这样就使得每个任务都有与之相对应的独一无二的优先级。因此,任务就绪状态就可以根据优先级别的数量建立一个表,通过这个表,调度器就可以决定下一次该哪个优先级的任务开始运行了。因为uC/OS-II任务最多只能是64个,Jean J.Labrosse 就把就绪表分成8*8的一个矩阵形表(table),这样就刚好能存放64个就绪的任务了。这样就有了下面的表格,里面的数字代表优先级。

    

这个表格就是OSRdyTbl[];按优先级将它分成了八组,每一行作为一组,每组八个任务,(也即按Y坐标分组)。

    uC/OS-II的就绪任务表从编程上面来看,实质上就是一个类型为INT8U的数组OSRdyTbl[ ]。其中的每一位对应一个任务。OSRdyTbl[]数组的一个元素就可以表示8个任务的就绪状态。为了方便对就绪表的查找,uC/OS-II又定义了一个数据类型为INT8U的变量OSRdyGrp,并使该变量的每一个位都对应OSRdyTbl[]的一个任务祖(即数组的一个元素)。如果某任组中有任务就绪,则在变量OSRdyGrp里把该任务组所对应的位置为1;否则置为0。

    2).下面来看看就绪表中两个变量OSRdyGrp和OSRdyTbl[],两者关系如下图:


这两个变量的对应关系是:OSRdyTbl[ n ] 中任何一位是1时,OSRdyGrp  的第n 位 是1。相当于OSRdyGrp是OSRdyTbl[]的数组下标索引。

      这个知识点要这么来理解:OSRdyGrp是一个有八位二进制数的数,它的每一位代表一个组。比如:OSRdyGrp的第0位代表了第一行0到7这八个优先级。第一位代表了8到15这八个优先级,以此类推。只要哪一组OSRdyTbl[n]中的任何一位置位(即哪一组中有任何一个任务进入就绪表),那么OSRdyGrp相应的位就置1。比如:第一行中优先级0到7,只要有一个任务进入就绪表,那么OSRdyGrp的第0位就会置1(有更多任务进入就绪表也会置1),表示这一行中有任务进入就绪表啦,所以我们说:OSRdyGrp等于是OSRdyTbl[]的数组下标索引。

3). 如何知道具体INT8U组OSRdyTbl[n]里面8个中间的哪一个任务就绪?

      开头我们已经说了,就绪表就是按优先级排成的矩阵,那么:由于优先级别是一个单字节的数字,而且其最大值不会超过63,即二进制形式的00111111,因此可把优先级看成是一个6位的二进制数。这样高3位(D5,D4,D3)来指明变量OSRdyGrp的具体数据位,并用来确定就绪表数组元素的下标。低3位(D2,D1,D0)来指明该数组元素的具体数据位。
      例如Prio=30的就绪任务,其二进制形式为00011110,其低6位为011110,于是D5,D4,D3为011,故任务在OSRdyTbl[3]上,因此OSRdyGrp的D3位置1,D2,D1,D0为110,故OSRdyTbl[3]上的D5位上要置1。


4).如何查表?

    

这就要看OSRdyTbl[]了。先来介绍一个掩码的知识:ucos里面有一个数组,叫OSMapTbl[],它来帮助我们查一个任务是否进入优先级。


具体如下:



OSMapTbl[]的下标


OSMapTbl[](即位掩码)


0


00000001


1


00000010


2


00000100


3


00001000


4


00010000


5


00100000


6


01000000


7


10000000


我们来看,一个任务优先级将它化成二进制数,它的低三位与它在哪一组没有任务关系!因为逢八才换组,而低三位最大才是七!但它能决定这个任务在一组的某个地方(即能决定X的值)而它的接下去三位与它在一组中的哪个位置没有任何关系!因为去掉低三位,接下去三位始终是八的倍数,始终指向组的首地址!但它能决定Y的值!这样,在一个矩阵中,X的值和Y的值都决定了,那么这个任务所在的位置就决定了。这样,使一个任务进入就绪状态和脱离就绪状态也就简单了。


其实不用这么麻烦,我们可以把表中的数看成是八进制的数,低三位看成是个位,接下来三位看成是进位,进位代表OSRdyGrp,个位代表OSRdyTbl[],个位无论怎么变,它都不会影响进位的位置,所以在哪一行只取决于OSRdyGrp,在哪一列只取决于OSRdyTbl[],口算也算出来了,呵呵。这样比较好理解一些。


这里可能大家有疑问:那不只取了优先级的六位吗?还有两位呢?这个不用着急,还有两位为零!因为最大才63,只需要用到六位,如果最高两位有任何一位为一的话,就会出错。所以我们就不用管最高两位了。


a. 使任务进入就绪状态的程序为:


OSRdyGrp             |= OSMapTbl[prio>>3];//确定它的行,置1   Prio的次高三位可以确定OSRdyGrp


OSRdyTbl[prio>>3]     |=OSMapTbl[prio&0x07];//确定它的列,置1   低三位可以确定OSRdyTbl[]

上面这两行代码还是很容易理解的:
先将prio右移3位,去掉X坐标占用的后三位,只取Y坐标,填入OSMapTbl[ ], 返回值与OSRdyGrp做位或,将OSRdyGrp对应位置1,表示该行有任务进入就绪态;例如,假设prio>>3 得到 Y坐标 = 3,则OSMapTbl[ 3 ] = 00001000,与OSRdyGrp做位或,将第四位置1;

第二条代码将prio与0x07=00000111 做位与,保留低三位,将其他位置0,得到X坐标,将X坐标填入OSMapTbl[ ],返回值与OSRdyTbl[ Y ]做位或,将OSRdyTbl[ Y ]对应位置1,表示该行的第X位有任务进入就绪态,注意第X位要从低端算起,也就是表格的右端开始算起;

例如:刚才已经算出Y坐标 = 3,假设prio & 0x07 = X坐标 = 4 ,OSMapTbl[ 4 ] = 00010000 ,将该返回值与OSMapTbl[ 3 ]做位或,将第五位置1,表示该位的任务进入就绪态;


b. 使脱离就绪态的方法:

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


c. 找出进入就绪态的优先级最高的任务


    这里作者Jean J.Labrosse 提供了一个查找表的,只要按照一定算法查找,很快就查出来了。


代码为:y = OSUnMapTbl[OSRdyGrp];


       x= OSUnMapTbl[OSRdyTbl[y]];


       prio = y<<3 +x;


这个表为:


这里 OSUnMapTbl[]同样是uC/OS-II为提高查找速度定义的一个数组,它共有256个元素,其定义如下

INT8U const OSUnMapTbl[] = {

    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

};


右边注释的值是代表OSRdyGrp的值。如果OSRdyGrp的值为01101000,即0x68,那么,我们可以根据右边的注释,要查第七行。是第七行的第八个(从0开始)。是3。再代入程序,算出x为2,将x和y 代入prio = y<<3 +x;,算出最高为26,再根据这个值,查出任务控制块优先级表,得到该任务的任务控制块。

原创粉丝点击