uc/OS-II在RAM中设立了一个记录表,系统中的每一个任务在表中占一个位置,并用这个位置的状态(0和1)来表示任务是否处于就绪状态。这个表叫作任务就绪状态表。算法
就绪任务表其实是一个类型为INT8U的数组OSRdyTbl[]。其中每一个字节的每一个位表示一个任务,这样一个数组元素就能够表示8个任务的就绪状态。以任务优先级别高低为顺序,好比OSRdyTbl[0]的第1位表示任务优先级0,OSRdyTbl[1]的第8位表示任务优先级15.当其位为1时任务处于就绪状态,0则为非就绪状态。数组
咱们能够把数组元素的8个任务当作是一个任务组,为了便于就绪表的查找,uc/OS-II又定义了一个数据类型为INT8U的变量OSRdyGrp,并使该变量的每个位对应OSRdyTbl[]的一个任务组(即数组的一个元素)。若是某任务组中有任务就绪,则在变量OSRdyGrp里把该任务组对应的位置置1,不然置为0。好比OSRdyGrp=0x00000011,则表示OSRdyTbl[0],OSRdyTbl[1]任务组中有任务就绪。spa
因为变量OSRdyGrp为8位,OSRdyTbl[]数组元素也有8位,因此算下来uc/OS-II就能够管理8x8=64个任务。下面是一张任务就绪表:源码
如何根据任务优先级别找到任务在就绪表中的位置。uc/os是这样设定的,因为优先级别是一个单字节的数字,并且其最大值不会超过63,即二进制形式的00111111,所以可把优先级别当作是一个6位的二进制数。这样就能够用高3位来指明变量OSRdyGrp的具体数据位,并用来肯定就绪表数组元素的下表,即上图中的Y。用低3位来指明该数组元素的具体数据位,即上图的X。因而根据任务的优先级别就能够肯定该任务在就绪表中的确切位置了。另外,uc/OS-II在初始化时建立任务就绪表,并把其中全部数据位都置位0。it
就绪表的操做有两项:一是把应就绪的任务在就绪表中进行登记,二是把任务从就绪表中删除。io
1.在就绪表中登记就绪任务变量
使用下面两行代码就能够把优先级别为prio的任务置位就绪状态。循环
OSRdyGrp |= OSMapTbl[prio>>3];数据类型
OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07];二进制
这就是根据上面的分析写出的代码。
其中OSMapTblp[]是uc/OS-II为加快运算速度定义的一个数组,数组以下:
INT8U const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
2.从就绪表中删除任务
优先级别为prio,代码以下
if((OSRdyTbl[prio>>3] &= ~OSMapTbl[prio&0x07]) == 0)
OSRdyGrp &= ~OSMapTbl[prio>>3];
其中若是OSRdyTbl[]数组元素每位为0的话,则相应OSRdyGrp的其中二进制位也要清零。
3.从就绪表中获取优先级别最高的就绪任务
其操做代码以下:
y = OSUnMapTbl[OSRdyGrp];
x = OSUnMapTbl[OSRdyTbl[y]];
prio = (y<<3) + x;
还有一种代码:
y = OSUnMapTbl[OSRdyGrp];
prio = (INT8U)((y<<3) + OSUnMapTbl[OSRdyTbl[y]]);
经过以上代码就能够找出最高优先级就绪任务的优先级别,其中OSUnMapTbl[]与OSMapTblp[]做用相似,是uc/OS-II为加快运算速度定义的一个数组,一共有256个元素。其数组以下:
INT8U const OSUnMapTbl[] = {
0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x00 to 0x0F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x10 to 0x1F */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x20 to 0x2F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x30 to 0x3F */
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x40 to 0x4F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x50 to 0x5F */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x60 to 0x6F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x70 to 0x7F */
7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x80 to 0x8F */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0x90 to 0x9F */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xA0 to 0xAF */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xB0 to 0xBF */
6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xC0 to 0xCF */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xD0 to 0xDF */
5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, /* 0xE0 to 0xEF */
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 0xF0 to 0xFF */
};
上面这个数组大有意思啊。刚开始我也好奇这是怎么来的,看了书而后仔细想一想就想通了,不得不感叹写源码的人的高明啊。
解释以下,由上面的代码看出,使用数组OSUnMapTbl[]时是以OSRdyGrp为下标的,所以这个数组一共有256个元素。也就是说,不管OSRdyGrp值为多少,在数组OSUnMapTbl[]总能找到对应的元素值,并且这个元素值就是最高就绪任务优先级别的y。由于数组OSUnMapTbl[]各元素的值是基于这样一个思想来设置的:表示任务组的变量OSRdyGrp是一个8位二进制数,从这个数的最低位向高位查找,碰到的第一个为1的位所对应的就绪任务组必定是最高优先级别就绪任务所在的组,因此它的组号必定是最高优先级别就绪任务的级别(6位数)的高3位。好比OSRdyGrp中第一个为1的位是第3位,那么最高优先级别就绪任务级别的高3位必定是011,因而在数组OSUnMapTbl[]的256个元素值中,凡是其下标值的第3位为1的元素值均定义为3.
因此有了这样一个数组,在查找最高级就绪任务时,只要以变量OSRdyGrp为下标,就可直接在在数组OSUnMapTbl[]获得就绪任务的y值了;不然,就要编写一个循环程序在就绪表中进行查找,这样不但耗时,并且犯了实时系统的大忌——运算时间不可预测。
固然此数组也用来查找最高就绪任务的x值。固然是以OSRdyTbl[y]为下表来查找的。这个跟超找y坐标相似。好比OSRdyGrp为0x28(00101000),最高优先组在OSRdyTbl[3],而OSRdyTbl[3]的元素为01100000,则第一个为1的位是咱们要找的最高优先级别的就绪任务。位5为1,则说明了x坐标为5,即最高任务优先级别的低3位确定为5。因而在数组OSUnMapTbl[]的256个元素中,凡是其下标为5的位为1的元素值均定义为5.
uc/OS-II常常使用这种相似于就绪表形式的表来记录任务的某种状态。这算不算一种算法呢?