ucos-II之任务优先级

很多关于UCOS的内核源码的文章已经很多也都和很好,但是我还是自己写下自己关于任务优先级确定的自己的一些看法。毕竟只有自己理解了才是自己的,才可以完全理解。

关于ucos任务优先级首先要确定一个变量任务优先级变量

1 priority ,这个变量在嵌入式实时操作系统邵贝贝译的书中76页,很清楚的可以看明白,priority 是个六位的变量,低三位组内偏移,高三位是组号

 问题:这个组是什么?

ucos总共可以有64个任务,每个任务优先级不同,所以可以有64个优先级,64个优先级可以分为8组,8个任务一组,所以前面priority变量保存的就是任务优先级的组号和组内偏移

2 priority 低三位会保存到一个变量中OSTCBY,高三位保存到OSTCBX,他们的取值范围都是0~7,见下面的代码

ptcb->OSTCBY = (INT8U)(prio >> 3);    ptcb->OSTCBX= (INT8U)(prio & 0x07);

3 由OSTCBY和OSTCBX作为索引从数组OSMapTbl取得OSTCBBitY和OSTCBBitX的值,先说OSMapTbl数组的定义

INT8U const OSMapTbl[8] = {0x01, 0x02, 0x04, 0x08, 0x10,0x20, 0x40, 0x80};

用二进制表示如下

OSMapTbl[]的下标

OSMapTbl[](即位掩码)

0

00000001

1

00000010

2

00000100

3

00001000

4

00010000

5

00100000

6

01000000

7

10000000

 

可以看出OSMapTbl数组中是一些分立的值,OSTCBBitY和OSTCBBitX的取值见代码

ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];

 ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];

这里OSTCBBitY还是表示的组别,OSTCBBitX表示的也是组内偏移,只是这里用的是二进制的表示方法,位图的方法表示

4 俩个非常重要的变量OSRdyGrp 和 OSRdyTbl[] 

OSRdyGrp是一个8位的变量,其中每一位表示8组任务中每一组是否有进入就绪态的任务

OSRdyTbl[]数组的每一位表示对应的组内是否有任务进入就绪态

于是俩个变量有这样的对应关系:

       当OSRdyTbl[0]中的任何一位是1时,OSRdyGrp的第0位置为1, // 1表示有任务进入就绪态

       当OSRdyTbl[1]中的任何一位是1时,OSRdyGrp的第1位置为1,

       当OSRdyTbl[2]中的任何一位是1时,OSRdyGrp的第2位置为1,

       ······

注意:

       1 OSRdyGrp是一个8位的变量,每一位是否为一表示对应的组是否有进入就绪态的任务

       2 OSRdyTbl[]数组不是8*8的二维数组,也不是大小为64的一维数组,是一个大小为8,每一个元素都是8位的数组

看看代码中的赋值:

       OSRdyGrp |=ptcb->OSTCBBitY;

       OSRdyTbl[ptcb->OSTCBY] |=ptcb->OSTCBBitX;

问题:

       1 为什么还有用这俩个变量,好像这俩个变量的值还是就绪任务的组名和组内偏移?

       答:首先要明白一点,OSTCBY,OSTCBX的取值范围为0-7,OSTCBBitX ,OSTCBBitY的取值范围为

0x01, 0x02, 0x04,0x08, 0x10, 0x20, 0x40, 0x80 那么OSRdyGrp的取值范围了,答案是从0x00到0xff。关键是OSRdyGrp |= ptcb->OSTCBBitY;用的是或。举个例子,当所有组都有就绪态任务的时候,那么OSRdyGrp的每一位都要为1,那么他的值也就是0xff。同理OSRdyTbl也是如此。所以明白了这一点就很容易理解为什么需要这俩个变量还有这俩个变量和前面有什么不一样。

5 如何确定优先级最高的任务?

思路:

    先通过OSRdyGrp确定就绪态优先级最高的任务组,然后通过OSRdyTbl找出组内优先级最高的任务

问题:

    现在OSRdyTbl和OSRdyGrp都是二进制的位图形式保存的,怎么样通过这些位图的形式来查找优先级最高的任务?举个例子,如果OSRdyGrp的值为0x80表示第7组内有就绪态任务,这里问题就出来了,我们怎么用0x80来索引得到这是表示第7组呢?

解决的关键在于一个数组OSUnMapTbl[],看看代码中的定义

INT8U  const  OSUnMapTbl[] = {
    0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x00 to 0x0F                             
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x10 to 0x1F                             
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x20 to 0x2F                             
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x30 to 0x3F                             
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x40 to 0x4F                           
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x50 to 0x5F                             
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x60 to 0x6F                             
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x70 to 0x7F                             
    7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x80 to 0x8F                             
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0x90 to 0x9F                             
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xA0 to 0xAF                             
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xB0 to 0xBF                             
    6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xC0 to 0xCF                             
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xD0 to 0xDF                             
    5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,       /* 0xE0 to 0xEF                             
    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0        /* 0xF0 to 0xFF                             
}; 

看看上面那个问题,我们把0x80的地方的值为7就解决了,当然前面我们说了OSRdyGrp的值是0x00到0xff所以一一对应出每一个值就变成了上面的这种表。组内偏移的索引也是这样的。

看看源代码:

y =OSUnMapTbl[OSRdyGrp];

 OSPrioHighRdy= (INT8U)((y << 3) + OSUnMapTbl[OSRdyTbl[y]]);

后面 y<< 3 位是因为y寻找的是组,每个组8个任务,左移三位就是乘以8,这个跟二维数组在内存中的索引一样。

至此一个UCOS的最高优先级的任务就确定了。






你可能感兴趣的:(嵌入式Linux)