zoukankan      html  css  js  c++  java
  • μC/OS Ⅱ之任务就绪表的操作_2012.5.31

    任务的登记:        

    1               OSRdyGrp |= OSMapTbl[prio>>3];
    2               OSRdyTbl[prio>>3] |= OSMapTbl[prio&0x07];

    这两行代码就实现了在就绪表中添加给定优先级(prio)任务的作用;

    想要彻底明白这两行代码,我们首先要对prio有了解。优先级prio,范围从[0:63],用二进制数表示,就是000000B~111111B。其中只用到了8位字长的低6位。这低六位又可以分为低三位和高三位:

    1            eg: 63=111 111B
    2               prio>>3  //即取prio的高三位,(绿色的3位);表示的是任务所在的组,即任务就绪表的Y坐标;
    3               prio & 0x07  //即取prio的低三位(红色的三位);表示的是任务所在的位,即任务就绪表的X坐标。

                                           

           OSRdyGrp是位可操作的,它的每一位对应Y坐标从0~7,表示任务就绪表的行,如果这一行中有任何一个优先级的任务就绪,就将它的对应位置1

           同理,数组OSRdyTbl[ ] 表示的是就绪表的每一行的内容,它的每个元素,也都是位可操作的,每个数组下标,表示Y坐标,即所在行,每个数组元素的内容,对应所在行的8个元素,也就是就绪表中每一行的8列。至此,构成了uC/OS-II的8X8的任务就绪表,可以表示0~63共64个优先级,这也是μC/OS Ⅱ支持的最大任务数为64的由来。

           再来看OSMapTbl这个数组,该数组已经定义好,它的8个元素分别是:

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

    下面回来看最初的两行代码:

    (1):prio>>3,就是只取prio的高三位,即任务所在的行(即坐标Y=prio>>3),将Y坐标填入数组OSMapTbl[Y]的下标中,OSMapTbl[Y]的值与OSRdyGrp做位或,将新就绪的任务所在的行所对应的OSRdyGrp的位 置1,并且保持其他位不变,如此一来,就新登记了一条就绪任务,并且没有影响到之前已就绪任务的登记信息;

           例如,本例中,假设prio>>3 得到OSMapTbl[prio>>3]=OSMapTbl[7] = 10000000B,再与OSRdyGrp做位或,即将OSRdyGrp的第8位 置为了1,并且没有改变其他位,同时没有影响到之前的就绪任务的已登记信息。

    (2):prio&0x07,就是只取prio的低三位,即任务所在的位(即坐标X =prio&0x07),将X坐标填入数组OSMapTbl[X]下标中,OSMapTbl[X]与OSRdyTbl[Y]做位或,将OSRdyTbl[Y]对应位 置1,表示该行的第X位有任务进入就绪态,注意第X位要从低端算起,也就是表格的右端开始算起;

      例如:刚才已经算出Y坐标 = 7,本例中,prio & 0x07 = 坐标X = 7 ,OSMapTbl[ 7 ] = 10000000B,将10000000与OSMapTbl[7]做位或,即将OSMapTbl[7]的第8位置1,表示该位的任务进入就绪态;如此,新就绪的任务登记完成,也保证了不影响其他任务的就绪状态。

    任务的注销:

    注销,就是说,从任务就绪表中将待注销任务的对应位 置0。

    1 if ( ( OSRdyTbl[prio >> 3] &= ~OSMapTbl[prio & 0x07] )  == 0)
    2     OSRdyGrp &= ~OSMapTbl[prio >> 3];

    注意:

    1.OSRdyTbl[prio>>3]所有的位都是0时,OSRdyGrp 的相应位才清零(即对   

    应行一个就绪任务都没有时,OSRdyGrp才为0)。所以要进行判断。2.OSRdyTbl[prio >> 3] 里面可能还包含其他位为1,即在RdyTbl[prio >> 3]   还有其他就绪任务,这时候所对应的OSRdyGrp 的位还是1,直到RdyTbl[prio >> 3] =0,表示没有任务就绪时才应将相应的OSRdyGrp里面的位置0

    以上第一行代码将就绪任务表数组OSRdyTbl[]中相应元素的相应位清零;同时做一个判断,判断OSRdyTbl[prio>>3]是否已全部为0,若全部为0,则表示改组任务全都不处于就绪状态,此时可把OSRdyGrp置为0。

    任务的查找:

    根据X和Y倒推算任务优先级prio:

    只需将以上运算倒过来即可:prio = [Y<<3] + X;

    例如:刚才上面的例子里,Y = 7,X = 7,则:

    1  prio = [Y<<3] + X = [7<<3] + 7
    2                    =(111B<<3)+111B
    3                    =111000B+111B
    4                    =111111B
    5                    =63D

    因此,进入就绪态的任务优先级为63。

    OSRdyTbl[ ]的元素(共8个元素,每个元素为8位;由此可见,任务就绪表就是一个从结构上来看,二维数组)构成8X8的就绪表,OSRdyGrp只表示就绪表的Y轴(所在行),也就是OSRdyGrp 中的每一位表示 8 组(行)任务中每一组(所在行)中是否有进入就绪态的任务。

    注意OSRdyGrp和OSRdyTbl[ ]的元素都是按位进行运算的。

    最高优先级就绪任务的查找:

           系统调度器总是把CPU控制权交给优先级最高的就绪任务,因此调度器就必须具有从任务就绪表中找出最高优先级任务的能力。

           基本的查找的思路是在任务就绪表里,从上至下,从右至左,挨个来找,但这需要大量的判断,因此花费很长时间。

           快速方法:根据y=OSRdyGrp( 所在组(行) )和OSRdyTbl[y](所在位)在优先级判定表OSUnMapTbl[ ]中,进行查表计算操作,即可快速计算出优先级最高的那个就绪任务。

    OSUnMapTbl[ ]如下所示:

     1 INT8U const OSUnMapTbl[256] = {
     2    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     3     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     4     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     5     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     6     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     7     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     8     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
     9     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    10     7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    11     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    12     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    13     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    14     6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    15     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    16     5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,      
    17     4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0       
    18 };

    计算代码如下:

    1 y = OSUnMapTbl[OSRdyGrp];         //最高优先级任务所在组(行)
    2 x = OSUnMapTbl[OSRdyTbl[y]];      //最高优先级任务所在的位
    3 prio = (y << 3) + x;              //还原为优先级

    注:

    1.OSUnMapTbl[]中的每个元素,表示的是从0x00—0xFF的每个数的二进制   数表示中,最低位1出现的位置。

    2.OSUnMapTbl[]中的每个元素,在0到7之间

  • 相关阅读:
    超强视频分割/剪辑软件-Ultra Video Splitter绿色便携版
    超强视频分割/剪辑软件-Ultra Video Splitter绿色便携版
    ASP.NET做WEB开发的工具选择
    ASP.NET做WEB开发的工具选择
    C#中的局部类型
    OpenCV2:幼儿园篇 第四章 访问图像
    OpenCV2:幼儿园篇 第三章 导出图像
    OpenCV2:幼儿园篇 第二章 读取图像
    OpenCV2:幼儿园篇 第一章 创建图像并显示
    MFC隐藏在黑暗之中的大坑
  • 原文地址:https://www.cnblogs.com/gylei/p/2528776.html
Copyright © 2011-2022 走看看