任何时刻系统中只能有一个任务在运行状态,各任务按级别通过时间片使它获得对CPU的访问权。任务就绪后进入就绪态,等待队列。通过调度程序使它获得CPU和资源使用权,从而进入运行态。任务在运行时因申请资源等原因而挂起,转入挂起态,等待运行条件的满足。当条件满足后,任务被唤醒进入就绪态,等待系统调度程序依据调度算法进行调度。任务的休眠态是任务虽然在内存中,但不被实时内核所调度的状态。任务还有一个状态,即被中断状态,它指任务在运行态时有中断请求到达,系统响应中断,转而执行中断服务子程序,任务被中断后所处的状态。多任务运行的实现是靠CPU在许多任务之间转换、调度。CPU只有一个,轮流服务于一系列任务中的某一个。多任务系统中,内核负责管理各个任务,并负责任务之间的通信。内核提供的基本服务是任务切换。内核对CPU的占用时间一般在2-5%之间。任务要获得CPU的控制权,从就绪态进入运行态是通过任务调度器完成的。任务调度器从当前已就绪的所有任务中,依照任务调度算法选择一个最符合算法要求的任务进入运行状态。任务调度算法的选择很大程序上决定了该操作系统的实时性能,这也是种类繁多的实时内核却无一例外选用特定的几个实时调度算法的原因。调度是操作系统的主要职责之一,它决定该轮到哪个任务运行。往往调度是基于优先级的,根据其重要不同被给于任务不同的优先级。CPU总是让处于就绪态的优先级最高的任务先运行。何时让高优先级任务掌握CPU的使用权,要看用的是什么类型的内核,是非抢占式的还是抢占式的内核。实时操作系统中常用的任务调度算法包括基于优先级的抢占式调度算法、同一优先级的时间片轮转调度算法和单调速率调度算法。1.1基于优先级的抢占式调度算法实时系统为每个任务赋予一个优先级。任务优先级在一定程序上体现了任务的紧迫性和重要性,越重要的任务赋予的优先级就越高。实时系统允许多个任务共享一个优先级,通过同一优先级的时间片轮转调度算法,完成任务的调度。优先级调度原则是让高优先级的任务在得到资源运行的事件上比低优先级的任务更有优先权。这保证了实时系统中紧急的、对时间有严格限制的任务能得到更为优先的处理,而相对不紧急的任务则等到紧急任务处理完后才继续运行。实时操作系统都采用基于优先级的任务调度算法。按照任务在运行过程中是否能被抢占,可以分为抢占式调度和非抢占式调度。1.1.1非抢占式调度非抢占式调度法也称为合作型多任务,各个任务彼此合作共享一个CPU。中断服务可以使一个高优先级的任务由挂起状态变为就绪状态。但中断服务以后控制权还是回到原来被中断的那个任务,直到该任务主动放弃CPU的使用权,那个高优先级的任务才能获得CPU的使用权。非抢占式内核的一个特点是几乎不需要使用信号量保护共享数据。运行的任务占有CPU,而不必担心被别的任务抢占。非抢占式内核的最大缺陷在于其响应高优先级的任务慢,任务已进入就绪态但还不能运行,也许要等很长的时间,直到当前运行的任务释放CPU。内核的任务级响应时间是不确定的,最高优先级的任务什么时候才能拿到CPU的控制权完全取决于应用程序什么时候释放CPU。见P27图1-6。由于其他任务不能抢占该任务的CPU控制权,如果该任务不主动释放CPU,则势必使系统进入死锁。每个任务在设计过程必须在任务结束时释放所占用的资源,它不能是一个无限运行的循环。这是非抢占式内核运行的先决条件。优点:*响应中断快。*可使用不可重入函数。由于任务运行过程中不会被其他任务抢占,各任务使用的子函数不会被重入,所以在非抢占式调度算法中可以使用不可重入函数。*共享数据方便。任务运行过程中不被抢占,内存中的共享数据被一个任务使用时,不会出现被另一个任务使用的情况,这使得任务在使用共享数据时不使用信号量等保护机制。当然,由于中断服务子程序可以中断任务的执行,所以任务与中断服务子程序的共享数据保护问题仍然是设计系统中必须考虑的问题。1.1.2抢占式调度当系统响应时间很重要时,要使用抢占式内核。最高优先级的任务一旦就绪,总能得到CPU的控制权。当一个运行的任务时,另一个比它优先级高的任务进入了就绪态,当前任务的CPU使用权就被剥夺了,或者说被挂起了,高优先级的任务立即得到CPU的控制权。抢占式调度算法满足在处理器中运行的任务是已就绪任务中优先级最高的任务。任务在执行过程中允许更高的优先级任务抢占该任务对CPU的控制权。与非抢占式调度算法不同的是当任务被中断,中断服务子程序运行完成后,不一定返回被中断的任务,而是执行新的任务调度,看就绪队列中是否有比被中断的任务拥有更高优先级的任务就绪。如果有,更高优先级的任务就调入并运该任务;否则,继续运行被中断的任务。如P28图1-7。抢占式调度算法的特点是任务级响应时间得到最优化,而且是确定的,因而中断响应较快。由于任务在运行过程中可以被其他任务抢占,所以任务不应直接使用不可重入函数,只有对不可重入函数进行加锁保护才能使用。同理,对共享数据的使用也需要互斥,信号量等保护机制。绝大多数的实时内核使用基于优先级的抢占式调度算法。在实时系统中,使用基于优先级的抢占式调度算法时,要特别注意对优先级反转问题进行处理。优先级反转问题体现的是高优先级的任务等待,属于被低优先级任务占有系统资源而形成的高优先级任务等待低优先级运行的反常情况。如果低优先级在运行时又被其他任务抢占,则系统运行情况会更糟。见P28实例。解决优先级反转的问题有优先级继承和优先级封顶两种方法。(1)优先级继承优先级继承要点如下:*设C为正占用某项共享资源的进程P以及所有正在等待占用此资源的进程的集合。*找出这个集合中的优先级最高者P_h,其优先级为P’。*把进程P的优先级设置为P’。见图P1-9。(2)优先级封顶优先级封项要点如下:*设C为所有可能竞争使用某项共享资源的进程的集合。事先为这个集合规定一个优先级上限P’,使得这个集合中所有进程的优先级都小于P’。注意:P’并不一定是整个系统中的最高优先级。*在创建保护该项资源的信号量或互斥量时,将P’作为一个参数。*每当有进程通过这个信号量或互斥量取得对共享资源的独占使用权时,就将此进程的优先级暂时提高到P’,一直到释放该项资源时才恢复其原有的优先级。优先级封顶是当任务申请某资源时,把该任务的优先级提升为可访问这个资源的所有任务中的最高优先级,这个优先级称为该资源的优先级封顶。资源的优先级封顶在资源被创建时就确定了。见P30图1-10。(3)优先级继承和优先级封顶的比较两种算法都改变了任务的优先级,但改变优先级的时间和范围有所不同。优先级继承只在占有资源的低优先级任务阻塞了高优先级的任务运行时,才动态更改低优先级的任务到高优先级。这种算法对应用中任务的流程影响较小。优先级封顶则不管任务是否阻塞了高优先级的任务运行,只要任务访问该资源,都会提升任务的优先级到可访问这个资源的所有任务的最高优先级。这两种算法各有优缺点,实际选择时根据具体情况而定。1.2同一优先级的时间片轮转调度算法对于复杂、高性能的多任务实时内核(如VxWorks),由于多个任务允许共用一个优先级,实时内核提供了同一优先级的时间片轮转调度算法来调度同优先级的多任务的运行。实时内核的调度器在就绪队列中寻找最高优先级的任务运行时,如果系统中优先级最高的任务有两个或两个以上,则调度器依照就绪的先后次序调度第一个任务。当其执行一段特定的时间片后,无论任务完成与否,处理器都会结束该任务的运行,转入下一个就绪的同优先级任务。未运行完的任务释放处理器的控制权后,放到就绪队列的末尾,等待下一个时间片来竞争处理器。当然,没有更高优先级的任务就绪,就应用基于优先级的可抢占调度算法。实时内核以轮转策略保证具有同优先级的任务相对平等地享有CPU的控制权。在时间片轮转算法中,时间片的大小选择会影响系统的性能和效率。时间片太小,任务频繁进行上下切换,实际运行程序的时间很少,系统的效率很低;时间片太大,算法变成先进先出算法,调度的公平性就没有得到体现。时间片的选择根据实时内核的不同而有所差异。1.2单调速率调度算法单调速率调度算法主要用于分配任务的优先级。它根据任务执行的频率确定优先级的。任务的执行频率越高,其优先级越高;反之,优先级越低。1.2任务间的通信在多任务的实时系统中,一项工作可能需要多个任务或多个任务与多个中断处理程序(ISR)共同完成。它们之间必须协调动作,互相配合,必要时还要交换信息。在实时操作系统中提供了任务间的通信与同步机制以解决这个问题。任务间的同步与通信一般要满足任务与其他任务或中断处理程序间进行交换数据;任务能以单向同步和双向同步方式与另一个任务或中断处理程序同步处理;任务必须能对共享资源进行互斥访问。1.2.1任务间的通信任务间的通信有两种方式:共享数据结构和消息机制。1.2.1.1共享数据结构实现任务间通信的最简单方法是共享数据结构。共享数据结构的类型可以是全局变量、指针、缓冲区等。在使用共享数据结构时,必须保证共享数据结构使用的排它性;否则,会导致竞争和对数据时效的破坏。因此,在使用共享数据结构时,必须实现存取的互斥的机制。实现互斥比较常用的方法有:开/关中断、设置测试标志位、禁止任务切换以及信号量机机制等。*开/关中断实现互斥指在进行共享数据结构的访问时先进行关中断操作,在访问完成后再开中断。*设置测试标志位方法指在使用共享数据的两个任务间约定时,每次使用共享数据前都要检测某个事先约定的全局变量。如果变量为0,则可读写,若为1,则不能。*禁止任务切换指在进行共享数据的操作前,先禁止任务的切换,操作完成后再解除任务禁止切换。这种方式虽然实现了共享的互斥,但是实时系统的多任务切换在此时被禁止,有违多任务的初衷,应尽量少使用。*信号量在多任务的实时内核中的主要作用是用做共享数据结构或共享资源的互斥机制,标志某个事件的发生,以及同步两个任务。信号量有两种:二进制信号量和计数信号量。1.2.1.2消息机制任务间的另一种通信方式是使用消息机制。任务可以通过系统服务向另一个任务发送消息。消息通常是一个指针变量,指针指向的内容就是消息。消息机制包括消息邮箱和消息队列。*消息邮箱通常是内存空间的一个数据结构。*消息队列实际上是一个邮箱阵列,在消息队列允许存放多个消息。对消息队列的操作和对消息邮箱的操作的操作基本相同。1.2.1任务间的同步任务同步中也常常使用信号量。与任务通信不同的是,信号量的使用不再作为一种互斥机制,而是代表某个特定的事件是否发生。任务的同步有单向同步和多向同步两种。*单向同步:标志事件是否发生的信号量初始化为0。一个任务在等待某个事件时,查看该事件的信号量是否为非0。另一个任务或中断处理程序在进行操作时,当该事件发生后,将该信号量置为1。等待该事件的任务查询到信号量的变换,代表事件已经发生,任务继续自身的运行。*双向同步:两个任务之间可以通过两个信号量进行双向同步。双向同步有两个初始化为0的信号量,每个信号量进行一个方向的任务同步,两个信号的同步方向是相反的。1.3存储器管理存储器管理是提供对内存资源的合理分配和存储保护功能。由于其应用环境的特殊性,实时内核的存储管理与一般操作系统的存储管理存在着很大的差异。通常的操作系统,资源充足,实时要求不高,其内核主要考虑提供更好的性能和安全机制。所以引入的是虚拟存储器管理。嵌入式实时操作系统的存储管理相对较为简单。由于虚拟存储器中经常要对页进行换入换出操作,所以内存中页命中率和换入换出所耗费的时间严重破坏了整个系统的确定性。这种存储机制不能提供实时系统所要求的时间确定性,对于大多数嵌入式实时应用来说,响应和运行时间的确定是至关重要的。对于实时应用,一个失去时效的正确结果与错误结果没有什么本质的不同,所以实时内核一般不采用虚拟内存管理。在大多数嵌入式实时操作系统中,内核把内存分成多个空间大小不等的分区,每个内存分区又分为许多大小相同的块。1.4定时器和中断管理实时内核要求为用户提供定时中断以完成延时与超时控制等功能。实时系统中时钟用来产生周期性的时钟节拍信号。时钟节拍一般为10-100次/秒之间。一个时钟节拍(Tick)值是用户应