Chinaunix首页 | 论坛 | 博客
  • 博客访问: 141963
  • 博文数量: 29
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 265
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-04 13:11
文章分类

全部博文(29)

文章存档

2015年(2)

2014年(27)

我的朋友

分类: 嵌入式

2014-01-14 09:30:49

实时系统的概念

实时系统的特点是,如果逻辑和时序出现偏差将会引起严重后果的系统。实时系统可分为:软实时系统和硬实时系统。

实时系统的宗旨是使各个任务运行得越快越好,并不要求限定某一任务必须在多长时间内完成。硬实时系统中,各任务不仅要执行无误而且要做到准时

1 前后台系统

后台行为(background):循环中调用相应的函数完成相应的操作,后台也叫任务级。

前台行为(foreground):中断服务程序处理异步事件,前台也叫中断级。


2 代码的临界段

代码的临界段也称为临界区,指处理时不可分割的代码。一旦这部分代码开始执行,则不允许任何中断打入。为确保临界段代码的执行,在进入临界段之前要关中断,而临界段代码执行完以后要立即开中断。

3 资源和共享资源

任何为任务所占用的实体都可称为资源。资源可以是输入输出设备,例如打印机、键盘、显示器,资源也可以是一个变量,一个结构或一个数组等。

可以被一个以上任务使用的资源叫做共享资源。为了防止数据被破坏,每个任务在与共享资源打交道时,必须独占该资源。这叫做互斥(mutual exclusion

4 任务和任务切换

任务,也称作一个线程,是一个简单的程序,该程序可以认为CPU完全只属该程序自己。每个任务都是一个无限的循环。

任务的五种状态:

休眠状态:该任务驻留在内存中,但并不被多任务内核所调度。

就绪状态:任务已经准备好,但该任务的优先级比正在运行的任务低,还暂时不能运行。

运行状态:指该任务掌握了CPU的控制权,正在运行中。

挂起状态:也可以叫做等待事件态WAITING,指该任务在等待,等待某一事件的发生,

中断状态:是当发生中断时,CPU提供相应的中断服务。

任务切换:入栈工作完成以后,就是把下一个将要运行的任务的当前状况从该任务的栈中重新装入 CPU 的寄存器,并开始下一个任务的运行。

5 内核和调度

内核:为每个任务分配 CPU 时间,并且负责任务之间的通讯。内核提供的基本服务是任务切换。内核本身也增加了应用程序的额外负荷,代码空间增加 ROM 的用量。

调度:内核的主要职责之一,就是要决定该轮到哪个任务运行了。实时内核是基于优先级调度法的。CPU 总是让处在就绪态的优先级最高的任务先运行。然而,究竟何时让高优先级任务掌握 CPU 的使用权,有两种不同的情况,这要看用的是什么类型的内核,是不可剥夺型的还是可剥夺型内核。

6 不可剥夺型内核与可剥夺型内核

不可剥夺型内核要求每个任务自我放弃 CPU 的所有权。各个任务彼此合作共享一个 CPU。异步事件还是由中断服务来处理。中断服务可以使一个高优先级的任务由挂起状态变为就绪状态。但中断服务以后控制权还是回到原来被中断了的那个任务,直到该任务主动放弃 CPU 的使用权时,那个高优先级的任务才能获得 CPU的使用权。

不可剥夺型内核的一个优点是响应中断快。几乎不需要使用信号量保护共享数据。最大缺陷在于其响应时间。商业软件几乎没有不可剥夺型内核。


可剥夺型内核:最高优先级的任务一旦就绪,总能得到 CPU 的控制权。当一个运行着的任务使一个比它优先级高的任务进入了就绪态,当前任务的 CPU 使用权就被剥夺了,或者说被挂起了,那个高优先级的任务立刻得到了 CPU 的控制权。如果是中断服务子程序使一个高优先级的任务进入就绪态,中断完成时,中断了的任务被挂起,优先级高的那个任务开始运行。

使用可剥夺型内核时,应用程序不应直接使用不可重入型函数。调用不可重入型函数时,要满足互斥条件,这可以用互斥型信号量来实现。μC/OS-Ⅱ属于可剥夺型内核。


7 可重入性

可重入型函数可以被一个以上的任务调用,而不必担心数据的破坏。可重入型函数任何时候都可以被中断,一段时间以后又可以运行,而相应数据不会丢失。可重入型函数或者只使用局部变量,即变量保存在 CPU 寄存器中或堆栈中。如果使用全局变量,则要对全局变量予以保护。

8 静态优先级与动态优先级

应用程序执行过程中诸任务优先级不变,则称之为静态优先级。在静态优先级系统中,诸任务以及它们的时间约束在程序编译时是已知的。

应用程序执行过程中,任务的优先级是可变的,则称之为动态优先级。实时内核应当避免出现优先级反转问题。

9 优先级反转

在这种情况下,任务 1 优先级实际上降到了任务 3 的优先级水平。因为任务 1 要等,直等到任务 3 释放占有的那个共享资源。由于任务 2 剥夺任务 3 CPU 使用权,使任务 1 的状况更加恶化,任务 2 使任务 1 增加了额外的延迟时间。任务 1 和任务 2 的优先级发生了反转。

为防止发生优先级反转,内核能自动变换任务的优先级,这叫做优先级继承(Priority inheritance)但μC/OS-Ⅱ不支持优先级继承,一些商业内核有优先级继承功能。


10 互斥条件

实现任务间通讯最简便到办法是使用共享数据结构。虽然共享数据区法简化了任务间的信息交换,但是必须保证每个任务在处理共享数据时的排它性,以避免竞争和数据的破坏。与共享资源打交道时,使之满足互斥条件最一般的方法有: 关中断,使用测试并置位指令,禁止做任务切换,利用信号量。

10.1关中断与开中断

μC/OS-Ⅱ在处理内部变量和数据结构时就是使用的这种手段,即使不是全部,也是绝大部分。实际上μC/OS-Ⅱ提供两个宏调用,允许用户在应用程序的 C 代码中关中断然后再开中断:OS_ENTER_CRITICAL() OS_EXIT_CRITICAL(),关中断的最长时间不超过内核本身的关中断时间

10.2测试并置位

如果不使用实时内核,当两个任务共享一个资源时,一定要约定好,先测试某一全程变量,如果该变量是 0,允许该任务与共享资源打交道。为防止另一任务也要使用该资源,前者只要简单地将全程变量置为 1,这通常称作测试并置位(Test-And-Set),或称作 TAS

10.2信号量

信号量实际上是一种约定机制,在多任务内核中普遍使用.信号量用于: 控制共享资源的使用权(满足互斥条件),标志某事件的发生,使两个任务的行为同步。

一般地说,对信号量只能实施三种操作:初始化(INITIALIZE),也可称作建立(CREATE);等信号(WAIT)也可称作挂起(PEND);给信号(SIGNAL)或发信号(POST)。信号量初始化时要给信号量赋初值,等待信号量的任务表(Waiting list)应清为空。

11 死锁

死锁也称作抱死,指两个任务无限期地互相等待对方控制着的资源。发生了死锁。最简单的防止发生死锁的方法是让每个任务都:

先得到全部需要的资源再做下一步的工作

用同样的顺序去申请多个资源

释放资源时使用相反的顺序

12 同步

可以利用信号量使某任务与中断服务同步(或者是与另一个任务同步,这两个任务间没有数据交换)

双向同步同单向同步类似,只是两个任务要相互同步。运行到某一处的第一个任务发信号给第二个任务,然后等待信号返回。同样,当第二个任务运行到某一处时发信号给第一个任务等待返回信号。至此,两个任务实现了互相同步。在任务与中断服务之间不能使用双向同步,


13 事件标志

当某任务要与多个事件同步时,要使用事件标志。若任务需要与任何事件之一发生同步,可称为独立型同步(即逻辑或关系)。任务也可以与若干事件都发生了同步,称之为关联型(辑与关系)

内核支持事件标志,提供事件标志置位、事件标志清零和等待事件标志等服务。事件标志可以是独立型或组合型。μC/OS-Ⅱ目前不支持事件标志。


14 任务间通信

有时很需要任务间的或中断服务与任务间的通讯。这种信息传递称为任务间的通讯。任务间信息的传递有两个途径:通过全程变量或发消息给另一个任务。

用全程变量时,必须保证每个任务或中断服务程序独享该变量。中断服务中保证独享的唯一办法是关中断。请注意,任务只能通过全程变量与中断服务程序通讯,而任务并不知道什么时候全程变量被中断服务程序修改了,要避免这种情况,用户可以使用邮箱或消息队列。

15 消息邮箱与消息队列

通过内核服务可以给任务发送消息。典型的消息邮箱也称作交换消息,是用一个指针型变量,通过内核服务,一个任务或一个中断服务程序可以把一则消息(即一个指针)放到邮箱里去。同样,一个或多个任务可以通过内核服务接收这则消息。发送消息的任务和接收消息的任务约定,该指针指向的内容就是那则消息。

每个邮箱有相应的正在等待消息的任务列表,要得到消息的任务会因为邮箱是空的而被挂起,且被记录到等待消息的任务表中,直到收到消息。一般地说,内核允许用户定义等待超时,等待消息的时间超过了,仍然没有收到该消息,这任务进入就绪态,并返回出错信息,报告等待超时错误。


消息队列用于给任务发消息。消息队列实际上是邮箱阵列。通过内核提供的服务,任务

或中断服务子程序可以将一条消息(该消息的指针)放入消息队列。同样,一个或多个任务可

以通过内核服务从消息队列中得到消息。发送和接收消息的任务约定,传递的消息实际上是

传递的指针指向的内容。一般遵循先进先出原则。


16 中断

中断是一种硬件机制,用于通知 CPU 有个异步事件发生了。中断一旦被识别,CPU 保存部分(或全部)现场(Context)即部分或全部寄存器的值,跳转到专门的子程序,称为中断服

务子程序(ISR)。中断服务子程序做事件处理,处理完成后,程序回到:

在前后台系统中,程序回到后台程序

对不可剥夺型内核而言,程序回到被中断了的任务

对可剥夺型内核而言,让进入就绪态的优先级最高的任务开始运行

17 中断延迟时间,中断相应时间,中断恢复时间

可能实时内核最重要的指标就是中断关了多长时间。关中断的时间越长,中断延迟就越长。中断延迟 = 关中断的最长时间 + 开始执行中断服务子程序的第一条指令的时间

中断响应定义为从中断发生到开始执行用户的中断服务子程序代码来处理这个中断的时间。中断响应时间包括开始处理这个中断前的全部开销。典型地,执行用户代码之前要保护现场,将 CPU 的各寄存器推入堆栈。这段时间将被记作中断响应时间。

         可剥夺型内核,则要先调用一个特定的函数,该函数通知内核即将进行中断服务,使得内核可以跟踪中断的嵌套。对于 μC/OS-Ⅱ说来,这个函数是 OSIntEnter(),中断响应 = 中断延迟 + 保存 CPU 内部寄存器的时间 + 内核的进入中断服务函数的执行时间。

中断恢复时间定义为微处理器返回到被中断了的程序代码所需要的时间。在前后台系统中,只包括恢复 CPU 内部寄存器值的时间和执行中断返回指令的时间。

对于可剥夺型内核,中断的恢复要复杂一些。典型地,在中断服务子程序的末尾,要调用一个由实时内核提供的函数。在μC/OS-Ⅱ中,这个函数叫做 OSIntExit(),这个函数用于辨定中断是否脱离了所有的中断嵌套。如果脱离了嵌套中断恢复时间 = 判定是否有优先级更高的任务进入了就绪态的时间 + 恢复那个优先级更高任务的 CPU 内部寄存器的时间 + 执行中断返回指令的时间


18 非屏蔽中断

中断服务必须来得尽可能地快,内核引起的延时变得不可忍受。在这种情况下可以使用非屏蔽中断。

在非屏蔽中断的中断服务子程序中,不能使用内核提供的服务,因为非屏蔽中断是关不掉的,故不能在非屏蔽中断处理中处理临界区代码。然而向非屏蔽中断传送参数或从非屏蔽中断获取参数还是可以进行的。参数的传递必须使用全程变量,全程变量的位数必须是一次读或写能完成的,即不应该是两个分离的字节,要两次读或写才能完成。

19 时钟节拍

时钟节拍是特定的周期性中断。这个中断可以看作是系统心脏的脉动。中断之间的时间间隔取决于不同的应用,一般在 10mS 200mS 之间。时钟的节拍式中断使得内核可以将任务延时若干个整数时钟节拍,以及当任务等待事件发生时,提供等待超时的依据。时钟节拍率越快,系统的额外开销就越大。

20 对存储器的要求

如果设计是前后台系统,对存储器容量的需求仅仅取决于应用程序代码。而使用多任务内核时的情况则很不一样。内核本身需要额外的代码空间(ROM)。因为每个任务都是独立运行的,必须给每个任务提供单独的栈空间(RAM)

总代码量= 应用程序代码+ 内核代码

RAM总需求= 应用程序的RAM需求+ (任务栈需求+ 最大中断嵌套栈需求) * 任务数

 

 

阅读(1728) | 评论(0) | 转发(0) |
0

上一篇:C语言程序题(一)

下一篇:#ifndef的用法

给主人留下些什么吧!~~