UCOS中的一些概念(2)
互斥访问
互斥访问时无论是在实时系统还是非实时系统中都是非常重要的,其核心就是保障对数据的安全访问。互斥访问的实现通常用到以下技术。
- 关中断
- test-and-set等操作
- 关调度
- 信号量
中断实现户次访问
实现数据的互斥访问最简单的方法就是中断方法,其实现思路如下:
1 | 关中断 |
在UCOS中就是使用的这种技术来对内部变量和数据结构进行访问的,对于中断的打开和关闭,UCOS提供了两个宏:OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()。使用方法如下:
1 | void Function (void){ |
Test-and-Set
对临界资源的访问还可以使用一个全局变量作为标记,当两个或多个进程要访问某临界资源时,须先检查标记看临界资源是否可访问。思路如下:
1 | Disable interrupts; |
如上实现使用关中断来保证了对标记变量的检查和设置过程的原子性,如果不用中断方法保证,则需要额外变量来实现这一过程,但某些CPU已经提供了Test-and-Set这类的原子指令,简化了其实现。
关闭和打开调度器
这种方法是在访问临界资源前将调度器关闭。这种方法没有关中断,因此在访问临界资源时是可以被中断的,但尽管如此,中断返回后仍然会回到中断点处继续执行而不会切换到其它任务,这中特性与不可剥夺的调度非常类似,唯一区别是,临界资源访问完毕后,打开调度器时,如果在临界资源访问期间有需要被调度执行的任务存在,则会在此时立即调度执行该任务。在UCOS中也提供了相应的开关调度器的宏:OSSchedLock(),OSSchedUnlock()。其实现思路如下:
1 | void Function (void) { |
信号量
信号量机制的实现对于系统中临界资源的访问是非常有利的,信号量的操作包括INITIALIZE,WAIT,SIGNAL。INITIALIZE是对信号量的初始化过程。WAIT是信号量减一的过程,通常WAIT操作须配合等待队列机制,如果进程请求资源,资源可用时,进程直接获得资源,资源不可用时,将进程加入资源等待队列直至资源可用。SIGNAL机制时信号量加一或唤醒等待队列中进程的过程,如果等待队列中无进程,则信号量加1,如果有进程则唤醒其中优先级最高的进程或最早进入等待队列的进程。在UCOS中,SIGNAL操作取出的是优先级最高的进程。如下是UCOS中使用信号量对临界资源进行访问的过程。
1 | OS_EVENT *SharedDataSem; |
死锁
死锁是两个或多个进程相互等待对方已占有资源的现象,形成死锁的条件主要有:
- 互斥访问
- 不可剥夺
- 占有并请求
- 循环等待
在许多系统设计中,对信号量等资源的获取通常会设计一个超时时间,如果超时就会释放该资源,这是一种死锁预防的方法,破坏的是产生死锁的条件中的不可剥夺条件。对于死锁问题,还有死锁避免,死锁检查,死锁解除等方法,这些方法是操作系统设计领域不得不考虑的问题。
同步与事件标志
同步机制时是在信号量机制的基础上对进程状态的同步,多个进程相互之间如果具有先后的依赖关系时,确保各进程正常有序地运行的关键也是同步机制。其简单例子如下:
1 | Task1() |
上例中Task1和Task2相互产生依赖,通过信号量来保证Task1与Task2的执行顺序。同步问题的经典例子是生产者消费者问题,对于此类问题重要的是理解其中的依赖关系。
事件标志是指对一组事件发生与否的表示,进程同步问题中,可能依赖于多个事件的或与关系,即进程等待多个事件中的其中任何一个事件的发生或进程等待其中所有事件的发生,其情形可用下图描述:
在UCOS中对事件标志的操作包括SET,CLEAR,WAIT操作。
进程间通信
进程间通信是系统设计中不可或缺的一部分,因为系统中的任务很多时候不是孤立存在的,它需要输入输出,在这个过程中可能涉及到进程与进程的通信,进程与中断服务例程的通信等。最简单的进程间通信是直接利用信号量机制来实现的事件的同步,但对于传递更加复杂的信息的需求可能就有一定的局限性。因此消息邮箱和消息队列便由此产生。
消息邮箱和消息队列是内核提供的一项进程间通信服务,所有数据通过内核管理的内存块进行中转,进程间通过内核提供的统一接口进行消息的发生和获取。
中断
中断是一种通知CPU异步事件发生的硬件机制,当中断发生时,CPU将保存进程上下文并跳转到中断处理程序执行。中断机制还很好地避免了处理器不断地事件发生所造成的CPU时间的浪费。
在实时系统环境下,关中断的事件必须要尽可能短,因为这会影响到中断延时,若延时过大,可能会导致中断丢失。
在不可抢占式内核中的中断处理过程如下:
在可抢占式内核中的中断处理过程如下:
中断延时
在实时系统中,最重要的一个指标可能就是中断延时了,因为在所有实时系统中,都用到了关中断来处理临界资源,在处理完毕后再打开中断。当中断关闭的时间越长,就需要更高的中断延时来保证中断不致丢失。如下为为多个中断在关中断时发生,并在重新开中断后处理的情形。
中断响应时间
中断响应时间一个中断信号产生到被处理的时间,在通常的不可抢占内核中,中断的响应时间如下:
中断延时+保存CPU上下文时间
在可抢占式内核中,中断的响应时间如下:
中断延时+保存CPU上下文时间+中断入口函数执行时间
在$\mu$C/OS-$\amalg$中,中断入口函数为OSIntEnter()
中断恢复
中断恢复是指中断处理结束后返回中断点或切换到更高优先级进程的过程(可抢占式系统)。
对于不可抢占式的内核,中断恢复的时间消耗主要包含如下两部分:
恢复CPU上下文的时间+执行返回中断点指令的时间
对于可抢占式内核,则更复杂些,包含如下三部分时间:
选择最高优先级进程的时间+恢复最高优先级进程上下文时间+执行中断返回指令时间
不可屏蔽中断(NMIs)
对于某些中断来讲,必须在产生中断后立即处理,不能让内核对其施加任何延时,否则可能会造成中断丢失,对这类中断称为不可屏蔽中断。
时钟嘀嗒
时钟中断在系统中是一个比较特殊的中断,它周期性产生,我们可以依靠它来的系统和任务定时。
以下用一个延时程序展示任务执行时间间隔的偏差和浮动。
情况1,当一个任务每隔一个时钟中断需要执行一次时,同时比它优先级高的任务执行所需的总时间远小于一个时钟中断时,这个任务能够顺利执行,但其执行间隔并不总时一致地等于一个时钟中断。
如下图所示:
情况2,当一个任务每隔一个时钟中断需要执行一次时,同时比它优先级高的任务执行所需的总时间远几乎等于一个时钟中断时,这个任务刚执行结束,可能又需要立即执行。
如下图所示:
情况3,当一个任务每隔一个时钟中断需要执行一次时,同时比它优先级高的任务执行所需的总时间远大于一个时钟中断时,这个任务将不能每隔一个时钟中断执行一次。出现这种情形可能时由于系统超过负荷了或者时系统设计有问题。解决这种问题的方法主要有:
- 增加处理器时钟频率
- 增加时钟中断间隔时间
- 重新分配任务优先级
- 避免使用浮点运算
- 使用编译器优化代码
- 用汇编写代码,达到执行时间最小化
- 如果可能更换同系列的更好的处理器
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 yxhlfx@163.com
文章标题:UCOS中的一些概念(2)
本文作者:红尘追风
发布时间:2018-02-04, 08:44:23
原始链接:http://www.micernel.com/2018/02/04/UCOS%E4%B8%AD%E7%9A%84%E4%B8%80%E4%BA%9B%E6%A6%82%E5%BF%B52/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。