实时操作系统
设计理念
通常,实时操作系统分为两大类:
事件驱动型。当一个高优先级的任务需要执行时,系统会自动切换到这个任务。这种根据优先级调度任务的方式称为抢占式任务处理。
时间触发型。每个任务在各自设定好的的时间间隔内重复、轮流调度。
时间触发型设计往往比较严格地调度任务,具有更好的多任务处理能力。多个任务被不停地轮流调度,在宏观上,就相当于一个CPU同时执行多个任务。
在过去,CPU在切换任务时往往需要多个机器周期,在这段时间内,CPU不能处理其他任何任务。例如,一个20 MHz的摩托罗拉68000处理器(1980年代后期),在切换任务时需要花费20微秒。(相比之下,一个100 MHz的ARM架构的处理器(2008年之后的)只需要3微秒。) 因此,早期的实时操作系统通过减少任务切换次数来避免消耗过多CPU时间。
任务调度
在典型的设计中,一个任务有以下三种状态:
正在运行(Running,正在CPU中执行)
待命(Ready,等待执行)
阻塞(Blocked,任务暂停,等待一个事件的发生,例如接收一组数据)
由于CPU在某个时间只能执行一个任务,大部分任务,在大部分时间,处于阻塞或待命状态。可能会有大量项目在待命列表里等待执行,这取决于系统所需的任务数量以及调度器的类型。
通常情况下,对于简单的时间触发式调度器来说,待命任务列表的数据结构的设计要尽可能缩短最坏情况下,程序在调度器关键部分的执行时间,以防止其他任务一直在待命列表中,无法及时执行。因此,在这种调度器中,应尽可能避免抢占式任务,甚至应该关闭调度器之外的所有中断。当然,待命任务列表的数据结构也应根据这个系统需要的最大任务数量做进一步的优化。
如果待命任务列表中的任务较多,双向链表是一个比较好的选择。如果待命任务列表通常包含少量任务,但偶尔会出现较多任务,任务应该根据优先级排序。这样一来,要寻找最高优先级的任务,就不必要在整个列表中一个一个地寻找。而插入任务需要从列表中的第一个任务开始,向后寻找,直到找到比要插入的任务优先级低的任务,然后插入到该任务之前;如果没有找到优先级更低的任务,就插入到任务列表末尾。
在寻找任务列表,准备插入任务的过程中,应该注意避免抢占。长的关键部分应分为多个小的部分分别执行。如果在寻找任务列表,要插入低优先级任务的时候,一个中断发生使高优先级任务进入待命状态,高优先级任务应该在低优先级任务被插入之前立马被插入列表和执行。
在更先进的系统中,实时任务和许多非实时任务共享运算资源,这时候待命任务列表会变得很长。在这种系统中,待命任务列表可能不适合用链表的结构。
调度算法
一些实时操作系统中常用的算法:
合作式调度
抢占式调度
Earliest Deadline First approach
Stochastic digraphs with multi-threaded graph traversal
RTOS举例
WinCE、VxWorks、μC/OS-Ⅱ等运用较广。Linux是作为通用操作系统开发的,其内核在实时处理能力上先天不足,部分网络开发社区将其经过改造能在一定程度上成为实时操作系统。
开放源代码&免费
Raw-OS[1]
CoOS[2]
开放源代码
RT-Thread[3]
eCos
Fiasco (L4 clone)[4]
FreeRTOS
Phoenix-RTOS
Nut/OS[5]
Prex
RTAI
RTEMS
RTLinux
SHaRK[6]
TRON Project
Xenomai[7]
CoOS[8]
非开放源代码
Ardence RTX
BeOS
ChorusOS
DNIX
DMERT
e-Tkernel
HOPEN OS
embOS (Segger)
INTEGRITY
ITRON
LynxOS
MERT
MicroC/OS-II
MQX RTOS[9]
Nucleus
OS-9
OSE
OSEK/VDX
OSEKtime
PDOS
Phar Lap ETS
PikeOS
Portos
pSOS
QNX
RMX
RSX-11
RT-11
RTOS-UH
RTXC
Salvo RTOS[10]
SIAN III
Symbian OS
ThreadX
VRTX
VxWorks
Windows CE
µnOS
UNIX-RTR
REX
HP-1000/RTE[11]
免责声明:以上内容版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。感谢每一位辛勤著写的作者,感谢每一位的分享。
- 有价值
- 一般般
- 没价值