uCOS II 系列文章之就绪表
预计阅读时间: 4 分钟
就绪表记录着等待运行的任务优先级号,优先级号也可以认为是任务 ID(系统任务有专用 ID) ,即一个任务只有唯一的一个优先级并且这个优先级对应着该任务,知道优先级,就知道了是哪个任务。她们是一一对应的关系。 就绪表大小可以裁剪,即可以小于 8 个字节大小。
就绪表是一个数组,以 0-63 个优先级为例(最高优先级为 0)。
使用二进制表示(这里从左往右数偏移,方便观察,一般来说都是从右往左的),方便说明。
以该数组为例(内容随便写的,如果都为 0 ,说明没有任务准备运行,但实际上空闲任务是一直处于就绪态),某一 bit 置 1 表示一个任务处于就绪态,准备运行。
从 OSRdyTbl[ 0 ] = 0100 0101 b(b 表示二进制) 内容中我们可以看出优先级为 0*8 + 1 = 1 、0*8 + 5 = 5 、0*8 + 7 = 7 的任务已经准备好,可以开始运行了。
从 OSRdyTbl[ 1 ] = 0000 0100 b(b 表示二进制) 内容中我们可以看出优先级为 1*8 + 5 = 13 的任务已经准备好,可以开始运行了。
从 OSRdyTbl[ 2 ] = 0001 0010 b(b 表示二进制) 内容中我们可以看出优先级为 2*8 + 3 = 11 、2*8 + 6 = 5 的任务已经准备好,可以开始运行了。
继续分析其他字节内容 ...........最后一个字节为 0 表示该组没有任务准备运行。
从当前的分析,可以由就绪表得出准备运行的任务:
随便找一个 bit 为 1 的位置,就说明一个任务处于就绪态,我们可以根据该任务在就绪表的位置计算优先级(优先级在 u/COS II 中就是任务代号,任务调度就是根据它进行调度)设置该 bit 在一个字节中的 bit 偏移为 x ,在数组中的字节偏移为 y(OSRdyTbl[ y ])
那么得出优先级公式为: priority = y*8 + x。
通过优先级我们也可以确定该任务是否处于就绪态:
OSRdyTbl[ Priority / 8 ] & (1 << (Priority % 8)) 如果不为 0 (注意这里左移是因为习惯上是从右边往左边数 bit 偏移位置的),那么表明该任务处于就绪态。否则就是没有就绪。
(以下二进制和上表内容无关,就别看上面的表了)
为了更快的对就绪表进行操作,任务控制块(每一个任务都有一个单独的任务控制块,记录着任务的一些信息)设置了两组变量记录优先级,
前面是实际的位索引(根据优先级计算得出),后面的两个是位掩码(根据位索引左移得出)。OSTCBY 记录该任务在就绪表中的哪一个字节,方便查找就绪表中的组号(即某一个字节,比如 OSTCBY = 1(从 0 开始),表示第二个字节),找到组号就可以通过 OSTCBBitX 对这个任务进行就绪和删除就绪操作了,因为 OSTCBBitX 记录着任务的位掩码,比如 0000 1000 b (这里从右往左数偏移,从 0 开始)表示偏移为 3。找到了组号(即某一个字节),又知道位掩码,就可以对就绪表中该任务的状态进行就绪(置 1 :OSRdyTbl[y] |= OSTCBBitX)和非就绪(清 0 ,OSRdyTbl[y] &=( ~ OSTCBBitX) )操作 , 不需要每次进行操作前都需要通过优先级计算这些信息了。
INT8U OSTCBBitY 可以用于对就绪组 OSRdyGrp(记录着就绪任务的组掩码,这是一个字节,其中一位置一,就表示该组有就绪任务,如:0000 1001 b,表示第 0 组和第 3 组有任务就绪)进行操作,当就绪表中的一个组为 0 时,就可以用 OSTCBBitY 删除就绪组,OSRdyGrp &= ~OSTCBBitY;增加就绪组 OSRdyGrp |= OSTCBBitY。
注意:就绪表是可以裁剪的,最少一个字节,在最低优先级大于 63 时,可以最大 32 个字节(这时分组单位是两个字节一组)。