今天看了任哲编著的《嵌入式实时操作系统UC/OS原理及应用》关于任务就绪表的结构的的讲解,终于弄明白了UCOS作者对任务算法的编程思想。之前看了邵贝贝的那个始终迷糊不解,不知道是自己最近理解力降低了,还是本身贝书没讲明白,不过现在弄懂了也是不算太晚。
ucos用一个类型为INT8U的数组OSTdyTbl[]来充当这个任务就绪表,在这个就绪表中,以任务的优先级别高低为顺序,为每个任务安排了一个二进制位,并规定该位的值为1表示对应的任务处于就绪状态,否则为0处于非就绪状态。
由下图可以看出,每个任务的就绪状态只占据一位,因此OSTdyTbl[]的一个元素可以表达8个任务的就绪状态。因此下图数组4个元素可以表达32个任务的就绪状态。也就是说每一个数组元素描述了8个任务的就绪状态,于是这8个任务就可以看成是一个数组。为了便于对就绪表的查找,ucos-II定义了一个数据类型为INT8U的变量OSRdyGrp,并使该变量的每一位对应OSTdyTbl[]的一个任务组(即数组的一个元素),如果某任务组中有任务就绪,就在变量OSRdyGrp中把该任务组所对应的那一位置1,否则置0。例如如果OSRdyGrp = 11001011,那么久意味着OSRdyTbl[0],OSRdyTbl[1],OSRdyTbl[3],OSRdyTbl[6],OSRdyTbl[7]任务组中有任务就绪。OSRdyGrp 变量有8位,则可以表示8个任务组,每个任务组又包含8个任务,那么UC/OS最多可以管理8*8=64个任务。
那么如何根据优先级来查找任务在就绪表中的位置呢?
如下图所示,可以把任务优先级看成是一个6位二进制数(2^6=64,刚好表示64个任务),这样可以用高三位来指明变量OSRdyGrp的具体数据位,并用来确定就绪表数组元素的下标,用低三位来指明该数组元素的具体数据位(即哪个任务)。
比如说某个任务的优先级prio = 30,其二进制形式为:00011110,即OSRdyGrp = 011= 3,即为就绪表中第3组,即OSRdyTbl[3]中的第110=6位置1,同时要把变量OSRdyGrp 的第3位置1
OSRdyGrp |= OSMapTbl[prio >> 3];
OSRdyTbl[prio >> 3] |= OSMapTbl[prio & 0x07];