【@.1 任务调度时机】

之前的一篇文章分析了具体的uCOS-II中的任务切换机制,是从函数调用的角度上分析的。这次我具体从整个程序运行的时间上来看,分析多种任务调度发生的时机。以下所有图片均可点击放大观察。

所有图中红色箭头表示中断级的任务切换,蓝色箭头表示任务级的中断切换。

1. 仅有一个任务,这种情况最简单。假设时钟节拍是1000次每秒,由定时中断产生,当节拍的时钟服务程序结束时会调用OSInitExit,退出中断,其中 将进行上下文切换,运行当前就绪状态优先级最高的任务,这里当然就是任务A、任务A中的代码比较简单,运行到最后时假设调用OSTimeDly(1)延时 一个周期,提示系统放弃CPU控制权,这时将进行任务切换到空闲任务Idle Task。空闲任务优先级最低,是一个死循环,仅仅让一个OSIdleCtr循环一次加一。可以看出,在一个时钟节拍的间隔,这个计数器可能加不止一次。 另外uCOS中还有一个统计任务,需配置打开,其中就是利用这个空闲计数器求出CPU有多少时间在空闲任务中,即有多少CPU占空比。通过图示分析可以看 出,很明显虽然任务A延时一个时钟周期,1ms,但是实际上将会少于1ms的延时。这就是为什么实际的延时中或多或少都会有延时抖动的现象,下面的很多例 子的延时抖动都可能比这种情况更加复杂。

2. 简单的中断,这里假设有一个外部中断,在图示处打断了任务A的运行。外部中断响应后进入服务函数,中断退出时调用OSInitExit进行任务切换,回到 刚才被中断的任务。所以刚才的任务A就被延后了一段时间允许,之后任务A再切换到空闲任务。很明显,这个时钟周期内空闲计数器OSIdleCtr会少加一 些,最后可以统计出CPU占用率会上升一些。

3. 中断函数中利用OSSemPost发送一个信号量,接受信号量的是任务B,其优先级大于任务A。于是在每次中断服务函数结束时会首先调度任务B执行,按照 图中任务B的代码只有一个OSSemPend可能会有等待挂起发送,之后任务B会因为等待接受信号量而调度会任务A继续执行。图中的画出了三个外部中断分 别出现在不同时期,其中第三个外部中断将导致任务B执行到一半遇到时钟节拍的产生。这时候任务B会挂起,将执行节拍中断服务程序,经过调度后会发现任务B 任然处于就绪状态,所以将继续运行任务B直到结束。最后这里可以看出空闲任务在每个时钟周期被挤得更少了,所以CPU的利用率更多。

4. 跟第三中情况类似,只不过这里任务B中加了一句OSTimeDly(3)延时3个时钟周期,这时可以知道,在任务B延时期间,只剩TaskA和空闲任务, 他们将不会因为任务B的延时而被挂起。延时结束时,时钟节拍将首先调度延时结束处于就绪状态的任务B,之后再运行原本的任务A。这种情况也简单的表示了 uCOS是怎样充分利用CPU资源的。

5.中断中调用OSTaskResume恢复任务B。这里只是想说明,Resume/Suspend跟Post/Pend的区别,前者是一旦恢复则一直运行,而后者是Post一次,Pend方运行一次。

6. 当用信号量通讯时,利用任务A来发送,控制高优先级的任务B接受信号量。可以看出,任务A发送一次信号量将会时任务B调度执行,此时任务A由于优先级低, 被挂起,当任务B运行一次循环后又Pend等待信号量,这时任务B被挂起,由下一个时间周期的任务A发送,周而复始。

7. 对于共享资源,可以采用图示方式编写。这种方式表明,当两个任务想要使用共享资源时,每个任务用Pend和Post的组合包围住想要操作的资源(比如一个 函数,一个公共变量)。其中一个任务用完资源后执行Post,将会使另一个Pend等待资源的任务得以往下执行,不论二者的优先级如何。图中的任务也包含 了每次时钟节拍对任务的延时作用。不过像这种信号量通讯的场合会涉及到优先级反转问题,我们后面会分析。

8. 这里演示了一个比较恶劣的中断嵌套实例,可以看出所有任务/中断级的任务调度只有等最后一层中断嵌套执行结束后才能执行,在中断嵌套中若使用Post或 Resume想要执行任务调度也只能等到嵌套结束才能执行。uCOS-II支持中断嵌套,不用担心中断的响应问题,但是一旦中断嵌套之后就会出现很多延时 的问题,将会导致整个系统的实时性下降,比如图示的TaskA就因为中断嵌套,并且因为中断嵌套结束后TaskB接受到信号量而执行,使得其延时效果大大 超出我们想象,而且中间还缺了一步时钟周期,甚至导致这个周期满负荷(空闲任务不会执行到)。虽然画的有点夸张,但是这不得不引起我们的注意。所以通常推 荐中断服务函数写的越短越好,一个好的方法是,清除了中断标志后仅仅发送一个信号量通知别的任务执行,将所有需要花时间运行的工作交给任务而不是留给中断 服务函数处理。

以上的分析包含了少量几个任务和间可能出现的常见情况,对于大型程序来说,任务的调度和中断的响应可能比这个更加复杂,需要更进一步分析。

【@.2 优先级反转】

图 示的情况将出现优先级反转。任务A和C需要处理一个共享资源,低优先级的任务C首先得到信号量,处理完成后Post发送信号量通知等待中的任务A得以运 行,任务A处理完共享信号量后Post,将使得等待中的任务C运行,而过了一段时间,任务B由于某种原因被恢复为就绪状态,则任务B会抢夺任务C的CPU 使用权,待任务B结束后任务C才得以进行,之后任务C发送信号量,通知任务A得以继续运行。

这将会使得任务A等待信号量的时间延长,看上去是优先级低于A的任务B先于任务A执行,这往往也是我们所不希望的。这个问题的原因就是因为任务C的优先级太低,所以解决这个问题时简单的方法就是动态修改进行共享资源操作的任务的优先级即可。于是引入了互斥信号量。

互 斥信号量跟普通信号量基本一致,区别在于通过Pend得到信号量的任务将会被动态修改其优先级。这里我们一般会设置一个比较高的优先级,如图所示,任务A 和任务C交替得到信号量,并且得到信号量时被赋予了一个更高的优先级。这时若任务B进入就绪状态就无法得以运行了。注意到这仅仅是uCOS-II的解决方 法,因为uCOS-II不支持多任务同一优先级。

【@.3 uCOS中的中断延时】

对于中断响应的问题,从硬件上每个CPU并不相同,可以参考我的这篇文章对ARM7系列的中断响应进行一个了解。而uCOS对于中断响应会有一套自己的办法进行统一处理。

之前分析的内容仅仅是从任务级别来进行分析,但实际上更深入一步分析,中断的响应,任务的响应都会有一定时间的延时,以图示为例。

当 一个任务运行中得到中断请求,会首先有一个硬件的响应时间。之后硬件会关闭中断标志,一般是在CPU的状态寄存器中的IRQ位置1禁止,随后跳入中断入口 地址。之后uCOS会进行自己的特殊处理,对中断进行接管。首先会保存CPU当前寄存器,并通知内核进入中断函数(一般是调用OSInitEnter函 数),之后编写代码重新打开中断,允许中断嵌套。之后将进入中断服务函数。这期间的时间就是中断响应时间。

当服务函数结束后,会调用OSInitExit进行任务调度。若此时有新的任务置于就绪状态并且优先级比原任务高,则将会进行上下文切换,恢复CPU寄存器,中断返回后进入新的任务执行。若没有心的高优先级任务,则会原路返回,回到原来的任务继续执行。

可以很明显的看到,经过uCOS接受的中断响应将变慢,但是由于这样能实现中断嵌套和丰富的任务调度,所以这样的中断延时是可以接受的。

uCOS-II中的任务切换-图解多种任务调度时机与问题的更多相关文章

  1. DE1-SOC开发板上搭建NIOS II处理器运行UCOS II

    DE1-SOC开发板上搭建NIOS II处理器运行UCOS II   今天在DE1-SOC的开发板上搭建NIOS II软核运行了UCOS II,整个开发过程比较繁琐,稍微有一步做的不对,就会导致整个过 ...

  2. iOS7中的ViewController切换

    转自:https://onevcat.com/2013/10/vc-transition-in-ios7/ iOS 7 SDK之前的VC切换解决方案 在深入iOS 7的VC切换效果的新API实现之前, ...

  3. Quartus II中FPGA的管脚分配保存方法

    一.摘要 将Quartus II中FPGA管脚的分配及保存方法做一个汇总. 二.管脚分配方法 FPGA 的管脚分配,除了在QII软件中,选择“Assignments ->Pin”标签(或者点击按 ...

  4. LTE 切换过程中的数据切换

    http://blog.sina.com.cn/s/blog_673b30dd0100j4p4.html LTE中的切换,根据无线承载(Radio Bearer)的QoS要求的不同,可以分为无缝切换( ...

  5. 在Quartus II中分配管脚的两种常用方法

    在Quartus II中分配管脚的两种常用方法 示范程序 seg7_test.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /* * ...

  6. 如何在Quartus II中设置Virtual pin

    为了验证FPGA工程中的某个模块的功能和时序的正确性,常常需要对其单独进行验证,但是这些模块通常都与内部的众多信号相连(如系统总线,中断信号线等),往往一个模块的对外接口引脚会多达几百个,对其单独仿真 ...

  7. Android 中Activity生命周期分析:Android中横竖屏切换时的生命周期过程

    最近在面试Android,今天出了一个这样的题目,即如题: 我当时以为生命周期是这样的: onCreate --> onStart -- ---> onResume ---> onP ...

  8. sql server中创建链接服务器图解教程

    转自sql server中创建链接服务器图解教程 1.展开服务器对象-->链接服务器-->右击"新建链接服务器" 注意:必须以数据库管理员身份登录(通常也就是sa帐号) ...

  9. 如何进行fragment中的来回切换?

    本文选自StackOverflow(简称:SOF)精选问答汇总系列文章之一,本系列文章将为读者分享国外最优质的精彩问与答,供读者学习和了解国外最新技术,本文为大家讲解如何进行fragment中的来回切 ...

随机推荐

  1. linux下redis4.0.2安装与部署

    一.redis的介绍 Redis是当前比较热门的NOSQL系统之一,它是一个key-value存储系统.和Memcache类似,但很大程度补偿了Memcache的不足,它支持存储的value类型相对更 ...

  2. Java虚拟机1:开篇

    1.前言 由于后期学习需要用到大量的JVM底层的东西,所有本人调整了一下学习计划,打算先从JVM入手,了解整个JAVA的运行机制,内存模型,编译原理等等一些底层的东西,这样在学习 后面的东西,会有一种 ...

  3. Mysql数据库,表中有中文时,select出来好多问号(?)的解决方法

    在QQ群里问了一些高手,同时参考了这篇文章:http://huangyunbin.iteye.com/blog/1113983,终于把这个问题搞定了. 首先,我用的是zip包的Mysql,直接解压使用 ...

  4. PHP------练习------投票

    练习------投票 一 .题目要求: 二 .做法 [1]建立数据库 表名:diaoyantimu 表名: diaoyanxuanxiang [2]封装类文件 <?php class DBDA ...

  5. generator 函数

    可以看做一个状态机, 生成的是一个迭代器对象, 可以用来遍历状态机里面的各种状态 创建方式 在函数名前面添加 * , 内部使用 yeild 来标注状态 特性 yield 只能在 generator 中 ...

  6. BindingException: Invalid bound statement (not found)问题排查:SpringBoot集成Mybatis重点分析

    重构代码,方法抛出异常:BindingException: Invalid bound statement (not found) 提示信息很明显:mybatis没有提供某方法 先不解释问题原因和排查 ...

  7. LeetCode20.有效的括号 JavaScript

    给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合. 左括号必须以正确的顺序闭合. 注意空字符串可被认 ...

  8. 苹果内购小结 - iOS

    此篇针对 iOS 支付进行一次小结,很久没碰这块了,有些方法 Apple 官方也进行了优化,故也将随之进行更新. 首先,code 部分将分为两部分,一部分在 appdelegate 中,另一部分单独封 ...

  9. webuploader实现上传视频

    之前有人让我做一个webuploader上传视频,但是一直没有时间,现在抽出了时间来.来完成以下这个简单的demo 第一步,上传视频和上传 图片有什么区别么? 其实是没有的,因为执行的操作都是上传,所 ...

  10. Mac连接Linux服务器

    1.终端命令 a).打开Mac的命令终端 b).输入ssh -p 22 root@101.200.86.233 它会提示你输入密码,输入正确的密码之后,你就发现已经登陆成功了.(22: 端口号 roo ...