uCOS-II为了保证CPU总是执行优先级最高的任务,每当任务状态发生变化时,就需要判断当前任务是否为最高优先级,不是的话就需要进行上下文切换。如何在需要进行任务优先级比较时,快速的将就绪态任务中优先级最高的读出。一种最简单的数据结构就是定义一个unsigned int类型的变量。变量长度为4字节共32位,如果用1代表任务就绪,用0代表任务未就绪,用相应的位来代表任务优先级,那么这样总共能定义32个任务。

如上图所示,第一行代表该位的取值,第二行代表位,那么总共定义了32个任务,优先级分别为0-31,其中优先级为0,、29、31的任务处于就绪状态。这个说白了就是定义了一个长度为32的bool型数组,下标代表任务的优先级,该下标对应的值便为任务的状态。如果要读出就绪表中处于就绪状态并且优先级最高的任务,那么执行这条语句:

for(i=0;i<32&&(!(num&(0x01<<i)));i++);

其中num为定义的unsigned int 类型的变量,执行完这条语句之后,i的值就是就绪任务中优先级最高的任务所对应的优先级。

这样做确实简单明了,但是定义的任务偏少,而且读出一个特定任务优先级所需要的时间是不定的,就是说上面读出优先级的那条语句的执行次数是不定的,这显然不能满足实时性系统的要求。

所以就有了uCOS-II的神来之笔,unsigned int类型的变量可以看做是长度为32的bool型数组,如果将这个数组从一维定义到二维,那么定义的任务数量将翻倍增长。如果这个二维数组的列数为8,那么8位二进制数刚好可以用unsigned char来表示,那么定义一个一维的unsigned char数组就可以表示这种二维的bool型数组,uCOS-II总共可以管理64个任务,那么unsigned char数组的长度为8,便可以定义出64个任务,刚好满足要求。定义完之后的数据结构如下。

假设这个数组为data[],那么在上图中,data[0]=0xA6,data[6]=0X37,在第一行中,优先级为1、2、5、7的任务处于就绪状态,如何快速的读出处于就绪状态且优先级最高的任务,最笨的办法就是遍历这个数组,依次取出数组中的每个元素,每取出一个元素,读这个元素各个位的值,从低到高,直到找出第一个位为1的那一位。用元素的下标乘8再加上该位的值,就是优先级最高的任务。这种做法显然效率很低,而且执行这个算法的所需要的时间不定。

这个算法效率低下的原因就是把时间浪费在了读取那些未就绪任务的状态,假设就绪态任务中优先级最高为103,那么依次读取前102个任务的状态值浪费了大量的时间,如果能想办法跳过一些前面未就绪的任务,那么算法的效率就大大提升。如果将所有的任务分组,每八个为一组,总共八组,定义一个unsigned char类型的变量,假设为grp,用这个变量的每一位代表一个任务组。只要这个任务组中八个任务其中有一个处于就绪态,那么就将这个变量相应的位置1,如果所有的任务都未就绪,那么就将这个变量相应的位置0。这样就达到了前面所说跳过一些未就绪任务的想法,在遍历数组查找优先级时,从低到高首先去读grp每一位的值,如果发现某一位值为0,就代表这个组没有就绪态的任务,就跳过这个组。这样遍历data数组时,步长从1变为了8。

解决了前面的问题后,这个算法效率还是有些低,原因在于遍历。假设grp的值为0XA0(1010 0000),遍历的结果是优先级最高的就绪态任务在第五组,

for(i=0;i<32&&(!(num&(0x01<<i)));i++);

上面这句代码执行了五次,时间浪费在这里了。如果将代码执行的次数降低到最小,并且是确定的,那么效率将会进一步提升。如果定义一个长度为256的unsigned char数组(假设为indexOf1),将grp的值作为下标,该下标处元素的值为该下标值从低到高第一次出现1的位的位置。举例来说,0XA0(1010 0000)从低到高第一次出现1的位的位置为5,那么indexOf1[grp]=5。同理indexOf1[0]=0,indexOf1[1]=0,indexOf1[2]=1,… 于是在uCOS-II源码中定义了这样一个数组

这样就不用执行前面所述的那句代码,直接通过下标在数组中查找即可,代码执行的次数降到了最低而且次数是确定的。

那么总结一下查找最高优先级的算法,首先将grp作为下标,在indexOf1数组中查找grp第一次出现1的位的位置(假设为y),旨在跳过前面未就绪的任务组。以y为下标,取出就绪表data[]数组中对应元素,继续以该元素为下标,在indexO1数组中查找该元素第一次出现1的位的位置(假设为x),旨在跳过同组中前面未就绪的任务。这样总共跳过的未就绪的任务个数为 y组+x 个。每组的任务为8,那么跳过的任务数就是y*8+3,那么就绪任务中优先级最高的就是该值。以下面的这张就绪表为例:

grp的值为0XE0(1110 0000),表示0-4组没有就绪的任务,5-7有就绪的任务。首先以grp为下标,indexOf1[grp]=5,取出就绪表中data[5],值为0X98(1001 1000),以0X98为下标,在indexOf1中取出indexOf1[0X98]=3,那么总共跳过了5组+3个共43个任务,那么就绪任务中优先级最高的就是43。

在uCOS-II源码中,grp定义为OSRdyGrp,就绪表data[]定义为OSRdyTbl[OS_LOWST_PRIO/8+1],indexOf1[256]定义为OSUnMapTbl[256],

查找代码为:

y      = OSUnMapTbl[OSRdyGrp];
x      = OSUnMapTbl[OSRdyTbl[y]];
prio = (y << 3) + x;

UCOS II怎么查找当前就绪表中,优先级最高的任务相关推荐

  1. FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析

    FreeRtos学习笔记(11)查找就绪任务中优先级最高任务原理刨析 怎么查找就绪任务中优先级最高的? tasks.c中声明了一个全局变量 uxTopReadyPriority,任务从其他状态进入就绪 ...

  2. uC/OS-II如何使任务在就绪表中进入就绪态与退出就绪态

    程序清单:使任务进入就绪态 OSRdyGrp               |= OSMapTbl[prio>>3];                                     ...

  3. oracle查询一列汇总,【学习笔记】Oracle数据筛选 查找oracle所有表中的特定列中的某些数据...

    天萃荷净 开发DBA反映,根据需求需要查找Oracle数据库中所有表中特定的列中指定的关键词的数据,和数据内容和数量 找出数据库中所有表表中REMARK列中含有WN.wind.wlr中表名和数量 de ...

  4. 计算机用公式找出第一名,用公式查找Excel工作表中重复数据

    前不久,一位网友求教,要求找出Excel工作表中的重复数据并在单元格中列出.我给出了一个数组公式供参考,但不是太符合要求,因为这个数组公式虽然找出了重复数据,但是如果将数组公式向下复制时超出了出现重复 ...

  5. Oracle 查找并删除表中的重复记录

    案例:一个应用表中的一个字段是主键,向表中插入数据时,先把数据放在临时表中(没有主键)然后再插入应用表. 这时候如果临时表中有重复数据,无论是主键字段businessid有重复,还是一整行有重复都会报 ...

  6. php中的css类怎么查找,CSS 样式表中的类和伪类

    在CSS中,模式(pattern)匹配规则决定那种样式规则应用于文档树(document tree)的哪个元素.这些模式叫着选择符(selector). 一条CSS规则(rule)是选择器{属性:值; ...

  7. μCOS-II中的任务就绪表及任务调度

    μCOS-II中任务就绪表及任务调度的操作以及OSUnMapTbl[]优先级的计算 在整理这个学期老师发的ppt中想起来了这个知识点,感觉很重要,当时也是迷糊了很久才搞懂: 主要写一些任务就绪表的结构 ...

  8. ucos II任务管理之一:挂起任务

    Ucos II 任务管理之一 创建好了任务之后,就已经初步跨进了ucos II 的编程了.随着进一步的编程,发现学会创建了任务还是不够的. 在我的项目里,需要实现485通信功能,我创建了任务1用于串口 ...

  9. IAR中移植UCOS II系统以及sourceInsight 使用

    ucos 学习笔记 1 sourceInsight 使用 CSDN参考链接 新建工程 第一步:project中new project 第二步:在高亮部分输入工程的地址,工程文件夹与IAR工程文件夹放在 ...

  10. uCOS-II系统中的任务就绪表

      多任务操作系统的主要工作是为系统中处于就绪状态的任务分配CPU资源,其中涉及的两个关键是:判断哪些任务处于就绪状态.确定哪个任务应该马上得到执行,即任务调度. 1. 任务就绪表   任务就绪表记录 ...

最新文章

  1. (二)Cacti监控
  2. git的author和commiter的修改
  3. linux socket 错误 Transport endpoint is not connected 在 recv shutdown 中的触发时机
  4. 【Git】Git-常用命令备忘录(三)
  5. 汉字的ascii码值范围_ASCII代码
  6. c++获取当前时间戳_python开发:python时间模块的使用
  7. 读懂现金贷产品的客群风险标签维度
  8. 白帽SQL注入实战过程记录(2)——根据information_schema组装SQL注入语句
  9. Atitit 外包管理规范attilax总结
  10. CCF201409-5 拼图(100分)【插头DP+状态压缩】
  11. hashmap扩容_面试官问:HashMap在并发情况下为什么造成死循环?一脸懵
  12. 记一次失败的电话面试
  13. Mac版Permute 3(万能视频转换器)
  14. 浅析分支定界法在SLAM技术中的应用
  15. 计算机网络 理解拥塞控制
  16. iOS问题记录 - Xcode 14安装低版本iOS模拟器
  17. Excel VBA:设置图表系列格式
  18. Python基础:第019课——窗口缩放事件、最小化状态及处理
  19. 通讯录查询系统的设计与实现
  20. 用python写一个函数_Python基础-函数篇

热门文章

  1. 有限状态机FSM的写法
  2. C#中的HashTable 和Dictionary对象
  3. win10连接共享打印机_win7共享出来的打印机部分电脑无法连接的问题
  4. ]flume高并发优化——(1)load_balance
  5. activity和service之间的相互通信方法
  6. 关于华为路由器下一跳的心得
  7. web CSS的知识- 关于后代选择器,子选择器,兄弟选择器的使用
  8. 常用SQL语句(1)
  9. XHTML跟HTML的区别
  10. redis通过lua脚本实现分布式锁