因为最近想在 stm32 上跑操作系统,所以开始学习 uC/OS-II。正好这学期有嵌入式实时操作系统这门课,但上课的教材内容是广义上的嵌入式实时操作系统,所以我在图书馆借了任哲老师的这本“嵌入式实时操作系统 uC/OS-II 原理及应用”这本书。
最近看到任务就绪表及任务调度这部分,关于对任务就绪表的操作主要包括登记、注销和从就绪表的就绪任务中找到优先级最高的任务。
根据书本上的内容对任务的登记和注销的代码是比较好理解的,比较难理解的是查找优先级最高任务的算法。
再查找优先级最高的任务时,用到了 OSRdyGrp 这个变量,OSRdyTbl 这个数组以及 OSUnMapTbl 这个用于查找的数组,前面两个的含义书上都有讲,主要是对于那个用于查找的数组的用法不太清楚。
用于查找优先级最高就绪任务的代码很简单,如下:
y = OSUnMapTbl[OSRdyGrp]
x = OSUnMapTbl[OSRdyTbl[y]]
prio = (y << 3) + x
y 是优先级的高三位,x 是优先级的第三位。
OSUnMapTbl 数组如下:
INT8U const OSUnMapTbl[256] = { 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 里为 1 的最低位就是优先级最高任务所在的任务组,在 OSRdyTbl 的 8 个任务组里,为 1 的最低位就是优先级最高任务在这个任务组里的位置。所以找优先级最高的任务就是找他的高三位和第三位,就是找一个 0~7 之间的数值,就是找下标。
因为这只是记录一下自己的想法,所以说的不是那么清楚,顺便贴上自己写的生成那个用于查找数组的代码
#include <stdio.h>
#include <stdlib.h>
#define uint8 unsigned char
int main()
{
uint8 redgrp;
uint8 map[256] = { 0 };
map[255] = 0;
int i;
for(redgrp=1;redgrp<255;redgrp++)
{
uint8 temp = redgrp;
for(i=0;i<8;i++)
{
if((temp&0x01)!=0)
{
map[redgrp] = i;
break;
}
else
{
temp>>=1;
}
}
}
for (i = 0; i<256; i++)
{
printf("%d ", map[i]);
if ((i + 1) % 16 == 0)
printf("\n");
}
return 0;
}
运行结果如下:
可以看到的确生成了那个数组,理解这个代码应该就理解 uC/0S-II 是怎么查找优先级最高的任务了。