就绪表 学习笔记

时间:2022-07-04 19:25:15
最近在看《嵌入式实时操作系统uCOS-II 》 不求甚解 但是好记性不如烂笔头,对于就绪表理解,参考原著,简单写一下自己的收获

需要完成 

1、如何把一个任务设置为就绪状态

2、如何把一个任务取消就绪状态

3、如何查找就绪表中优先级最高的任务


任务的优先级 prio 可以由用户设定,在uCOS中,任务的优先级总共64个,被分为8组,每组8个,所以这里又出现两个参数 :

 1: OSRdyGrp是一个八位的无符号字符型数据。 对应相应的分组有任务就绪,OSRdyGrp二进制数据相应的位就会被置 1, 例如第0组中有任务就绪,则 OSRdyGrp |= 0x01;

                 
         2:OSRdyTbl [ ] 对应相应分组下的具体优先级别(注意:OSRdyTbl是一个八个字节的数组,假设第0组中有任务就绪,则OSRdyGrp的第0位将会被置 1 ,同理 如果第2组中有任务已经就绪,则OSRdyGrp的第2位将会被置1)
所以 不难发现,优先级 prio 和这两个参数之间符合这样的关系

[html] view plaincopy
  1. OSRdyGry                  |= OSMapTbl [ prio >> 3 ];  
  2. OSRdyTbl [  prio >> 3 ]   |=  OSMapTbl [ prio & 0x07 ];  


如果想要将某个任务设置为就绪状态,通过以上运算即可,
1、 首先判断出是哪一个分组OSRdyGry,将相应位置 1 
2、 然后判断出在该分组下具体是哪一个任务优先级 将 OSRdyTbl[ i ]相应字节的相应位置1 ,
(i 是数组的下标 i)i =  prio >> 3


OSMapTbl是一个八个字节的数组 ,已经预先设置好了


OSMapTbl [ 0 ] == 00000001 b
OSMapTbl [ 1 ] == 00000010 b
OSMapTbl [ 2 ] == 00000100 b
OSMapTbl [ 3 ] == 00001000 b
OSMapTbl [ 4 ] == 00010000 b
OSMapTbl [ 5 ] == 00100000 b
OSMapTbl [ 6 ] == 01000000 b
OSMapTbl [ 7 ] == 10000000 b



大致了任务就绪表,现在需要将一个任务取消就绪状态,那么只要将上述步骤做一个逆运算即可得到,下面就是如何取消一个任务的就绪状态的相应解释


任务处于未就绪状态需要将OSRdyGry、OSRdyTbl [  prio >> 3 ]  清零即可,

首先传入参数为相应任务的优先级,所以prio是已知的,因此就可推算出该任务在就绪表中的位置,参考原书中的算法


[html] view plaincopy
  1. OSRdyTbl [  prio >> 3 ] & = ~ OSMapTbl [ prio & 0x07 ]  ;  
  2. OSRdyGry &= ~OSMapTbl [ prio >> 3 ];  


 一般来说 ,如果同一分组中有两个以上的任务就绪,那么只需要进行第一步运算即可,将相应位的清零,即取消了相应prio优先级任务的就绪状态,如果进行了第二步运算,那可能会产生冲突,例如 第 0 分组 的1、2、3、4优先级的任务都处于就绪状态,因此 OSRdyGry 的第0位是被置 1 的,当你取消了 优先级为 1 的任务的就绪状态,第 0 分组仍然有2、3、4优先级处于就绪状态,所以如果进行第二步运算将OSRdyGry置0 则会产生错误。


接下来的问题是如何从任务就绪表中找到优先级最高的任务,即求出prio的值;

在CPU_CORE.C中定义了一个OSUnMapTbl [ 256 ] 的表 通过查表的方式可以快速求出优先级

书中例子可知 ,假设


                      OSRdyGry = 01101000 b ;


通过查表可知 OSUnMapTbl [OSRdyGry ] == 3;
其实也可以发现OSRdyGry = 01101000 b 时,第3、 5 、6位被置1 ,所以第3、 5 、6组中有相应任务就绪,在uCOS中规定prio数值越小 ,优先级越高,而且就绪表也是递增排列的,所以可以知道 是第 3 组 中存在最高优先级的任务
然后找到 第三组中被置1的最低位即可,当然这些操作直接查表即可,用空间换时间,提高了系统切换过程中 对就绪表一些操作的时间。