1、实时系统中的 POSIX 及 Case Study每个 RTOS 都有其专有 API,不过其中一些也支持 POSIX 标准。本文考察 POSIX 中应用于实时系统的部分。在今日的计算系统中,利用为业界接受的标准设计开放系统体系结构的软件正变得越来越重要。开发开放系统的需求被 3 个原因驱使着,第一,一个开发人员就能从头实现整个系统的日子已经一去不复返了。程序的规模正在不断变大,需要不断壮大的开发团队;第二,软件不再是孤立的,他们必须和数量极为庞大的商业软件共存;最后,软件应用程序的生命期通常都很长,增加新功能时需要进行各种修改和升级。通过定义可以提高互用性和可移植性的标准软件接口,开放的软件体
2、系结构适应了当今软件开发过程的挑战。公开发布的标准接口也减少了将来增加功能的花费。当今的计算机系统中广泛使用了各种标准。各种新的标准也正在不断定义以满足软件技术不断变化的状态。一个标准不被实际使用就不会产生有效的作用,或者马上就会过时。要发挥有效的作用,标准必须基于公认的技术并且被工业界广为接收。最初的 Portable Operating System Interface for Computing Environment(POSIX)标准于1990 年首次发布【1】 。POSIX 是基于 UNIX 的,后者在上世纪 70 年代已经成为一项被广为接受的技术。POSIX 定义了应用与操作系统接
3、口的标准方法。最初的 POSIX 标准定义了一些核心功能的接口,比如文件操作,进程管理,信号和设备。随后的 POSIX 发布还涵盖了实时扩展和多线程【1】 。在理想的世界里,由于前面提到的优越性,人们应该总是选择标准。不过在真实世界里,决定使用标准之前必须解决一系列问题。包括: 标准提供了我的应用需要的功能吗? 标准的性能,或者标准的实现,是否适合我的应用? 有这个标准的商业可用实现吗?本文将通过三个方面讨论 POSIX 在实时系统中的有用性:功能 functionality,性能performance 和可用性 availability。由于实时系统通常对性能有严格的限制,重点将放在POSI
4、X 实现的性能上。POSIX 实时操作系统POSIX 标准家族包括 30 多个独立的标准,从基本的操作系统服务规范到测试操作系统对标准的符合程度的规范【2】 。本文的重点是那些对实时嵌入式系统开发具有重要意义的标准。本节讨论实时系统并给出对相关 POSIX 标准的简要的 review。实时系统实时系统的计算结果及时性是相当重要的【3】 【4】 。比如军用武器系统,工业控制系统和视频音频流。实时系统通常分为两类:硬实时和软实时。硬实时系统中 deadline 必须满足否则计算结果就是无效的。例如,在导弹跟踪系统中,如果导弹延迟了就可能错过目标。软实时系统的时间限制没有这么严格。如果没有满足 de
5、adline,计算结果可能仍然是有用的。音频流就是一个软实时系统的例子。如果一个数据包迟到或者丢失了,声音质量会降低,不过仍然是可以听见的。为了保证实时系统的时间需求能够满足,下层计算系统的行为和时间特性必须是可预测的 predictable【5】 。系统时间性能称为可预测的的就是所有操作的时间必须有界。这意味着所有操作在最坏情况下的时间已知。不过有时,仅当其最坏情况时间和通常情况时间非常接近时系统才称为可预测的。POSIX 实时相关标准在 30 多个 POSIX 标准中,表一列出的 7 个标准和实时嵌入式系统的开发非常相关。头 3 个标准 1003.1a,1003.1b 和 1003.1c
6、是被支持最广的。POSIX 1003.1a 定义了基本操作系统功能的接口,它是在 1990 年 1 月被首个采纳的标准【6】 。实时扩展定义在1003.1b,1003.1d,1003.1j 和 1003.21 标准中【7】 【8】 【9】 【10】 。不过,最初的定义在1003.1b 中的实时扩展是唯一被广泛实现的。进程中的多线程支持在单独的标准 POSIX 1003.1c 中提供。POSIX 还在 1003.1h 标准中包括了高可用 high availability 支持【11】 。表一 POSIX 标准标准 名字 描述1003.1a OS 定义 基本 OS 接口;包括的支持有:单进程,多
7、进程,作业控制,信号,用户组,文件系统,文件属性,文件设备管理,文件锁定,设备 I/O,设备相关控制,系统数据库,管道,FIFO 和 C 语言1003.1b 实时扩展 实时系统需要的功能;包括的支持有:实时信号,优先级调度,定时器,异步 I/O,优先级 I/O,同步I/O,文件同步,映射文件,内存锁定,内存保护,消息传递,信号量1003.1c 线程 支持单进程内多线程的功能:包括的支持有:线程控制,线程属性,优先级调度,互斥量,互斥量优先级继承,互斥量优先级天花板和条件变量1003.1d 附加的实时扩展附加的接口;包括的支持有:新的进程创建语义(spawn ) ,sporadic server
8、 调度,进程和线程执行时间监视,I/O 咨询信息,阻塞功能上的超时,设备控制和中断控制1003.1j 高级实时扩展 更多的实时功能,包括:typed memory,nanosleep improvements,barrier 同步,reader/writer locks,spin locks 和 persistent notification for message queues1003.21 分布式实时 支持实时分布式通信的功能:包括的支持:缓冲管理,发送控制阻塞,异步和同步操作,边界阻塞,消息优先级,消息标签和实现协议1003.2h 高可用 可靠性,可用性和适用性服务(SRASS) ;包括
9、的支持:记账,核心转储控制,关闭/重启和重配置POSIX 的商业支持有相当大的不同。由于 POSIX 1003.1a 是基于 UNIX 的,任何基于UNIX 的操作系统会很自然的接近标准。要符合 POSIX 标准,操作系统和硬件平台必须使用一组测试通过认证【12】 。目前,只有用于 POSIX 1003.1a 的测试集。由于 POSIX 被设计为一组可选的特性,操作系统提供商可以选择仅实现 POSIX 的一部分并且仍然是 POSIX兼容的。兼容性只要求提供商说明 POSIX 的哪些特性实现了,哪些没有。这是混乱的一个根源,出于市场的原因,几乎所有的提供商都宣称他们是 POSIX 兼容的。POS
10、IX profiles嵌入式系统通常有空间和资源限制,包含全部 POSIX 特性的操作系统可能并不适用。定义 POSIX 1003.13 profile 标准就是用来满足这种类型的系统的需要的【13】 。POSIX 1003.13 并没有包含任何新增加的特性,它将已存在的 POSIX 标准定义的功能分组为不同的功能单元。该 profile 基于操作系统是否支持多进程和文件系统。4 个当前的 profiles 在表二中概述。表二 POSIX 1003.13 profilesProfiles 进程数量 线程 文件系统54 多个 Yes Yes53 多个 Yes No52 单个 Yes Yes51
11、单个 Yes NoPOSIX 实时扩展POSIX 1003.1b 以及 1003.1d,1003.1j ,定义了实时系统开发中有用的扩展。最初的实时扩展标准 1003.1b 中定义的功能已经被很多操作系统支持,后两个标准被支持的程度则没有这么广。出于这个原因,本文的重点在 POSIX 1003.1b。POSIX 1003.1b 中定义的特性的大概情况: 定时器 timers:周期性 timer,使用 POSIX 信号完成发送 优先级调度 priority scheduling:固定优先级克可抢占调度,最少 32 个优先级 实时信号 real-time signals:增加的具有多个优先级的信号
12、 信号量 semaphores:有名和内存计数信号量 内存队列 memory queues:使用有名队列的消息传递 共享内存 shared memory:多个进程共享的有名内存区域 内存锁定 memory locking:防止物理内存页的虚拟内存交换列表一是创建和使用 POSIX timer 的 C 代码。创建 timer 有两个步骤:指定 timer 到期时发送的信号,然后创建设置 timer 本身。例子中使用了最高优先级的实时信号SIGRTMIN 来异步调用 timer 处理例程。必须指定 timer 的两个值:初始到期时间 it_value和频率 tv_sec。结构 itimersepc
13、 允许纳秒级的时间规格,不过真正的精度和系统有关。POSIX 调用 clock_getres()可以用来确定真正的时间精度,通常是 10ms 或者 1ms。列表一#include #include void timer_create(int num_secs, int num_nsecs)struct sigaction sa;struct sigevent sig_spec;sigset_t allsigs;struct itimerspec tmr_setting;timer_t timer_h;/* setup signal to respond to timer */sigemptys
14、et(sa.sa_flags = SA_SIGINFO;sa.sa_sigaction = timer_intr;if (sigaction(SIGRTMIN, sig_spec.sigev_notify = SIGEV_SIGNAL;sig_spec.sigev_signo = SIGRTMIN;/* create timer, which uses the REALTIME clock */if (timer_create(CLOCK_REALTIME, /* set the initial expiration and frequency of timer */tmr_setting.i
15、t_value.tv_sec = 1;tmr_setting.it_value.tv_nsec = 0;tmr_setting.it_interval.tv_sec = num_secs;tmr_setting.it_interval.tv_sec = num_nsecs;if ( timer_settime(timer_h, 0, /* wait for signals */sigemptyset(while (1) sigsuspend(/* routine that is called when timer expires */void timer_intr(int sig, sigin
16、fo_t *extra, void *cruft)/* perform periodic processing and then exit */POSIX 1003.1b 提供了固定优先级可抢占调度的支持。要兼容 POSIX,操作系统必须实现至少 32 个优先级。POSIX 定义了 3 种调度策略操作同优先级的进程。SCHED_FIFO,按先进先出调度进程,进程运行直到完毕;SCHED_RR,调度器使用一个时间定额以循环方式调度进程;SCHED_OTHER,由实现确定调度策略。由于SCHED_OTHER 与实现有关,所以在不同平台间没有可移植性,应该有限制的使用。POSIX 在多种机制中都使用
17、有名对象,包括信号量,共享内存和消息队列。名字与文件系统名字类似,但是独立于后者。例如信号量,一个进程创建信号量,其他进程可以通过名字使用信号量。两个进程都可以进行释放 sem_post 和等待 sem_wait 操作。POSIX 线程POSIX 线程在一份独立的规范中实现,这意味着,它们的规范独立于其他实时特性【14】 。所以,很多实时规范中的特性也记入了线程规范中。例如,优先级调度是在各线程基础上进行的,但是处理方式却类似于 POSIX 1003.1b 中的调度。线程的优先级和调度策略通常都是在创建时指定的。POIX 线程规范定义并且(或者)修改了 POSIX 的如下方面: 线程控制 th
18、read control:创建,删除和单独线程管理 优先级调度 priority scheduling:POSIX 实时调度扩展到包括对每个线程基础上的调度;调度的范围达到所有进程内的所有线程或者只在每个进程间 互斥量 mutexes:用来保护代码的临界区;互斥量还包括防止优先级翻转的优先级继承和优先级天花板协议支持 条件变量 condition variables:与互斥量联合使用,条件变量用于创建监管同步结构 monitor synchronization structure 信号 signals:能够向独立的线程发送信号操作系统实现中 POSIX 的覆盖情况表三展示了 POSIX 100
19、3.1a 的兼容级别。LynxOS 3.1 release 兼容所有三个标准。VxWorks 只支持 POSIX 标准的一个子集,因为在 v5.4 及其以前的发布版本中,VxWorks基于单进程模型,没有包括任务内存保护。现在的发布版,VxWorks AE 已经支持内存保护;不过,保护模式是用和传统 POSIX 进程模型不同的方法实现的。Linux 提供了对基本POSIX API 和线程的很好支持,不过丧失了诸如时钟和消息队列的特性。表三 商业操作系统中的 POSIXOS POSIX 1003.1a(Base POSIX)POSIX 1003.1b(Real-time extensions)P
20、OSIX 1003.1c(Threads)Solaris Full support Full support Full supportLynxOS Conformant Full support 3.0.1 基于草案,没有线程属性;3.1 基于最终标准VxWorks部分支持;支持不需要进程模型的功能部分支持;支持不需要进程模型的功能通过第三方产品支持IRIX Conformant Full support Full supportLinux Full support 部分支持,不支持定时器和消息队列Full supportQNX NeutrinoFull support 接近 full sup
21、port;不支持内存锁定Full support操作系统设计操作系统的设计极大的影响着其作为实时系统使用的能力。这其中既包括操作系统内部设计也包括其提供给应用编程者的特性。本节的重点放在两个操作系统(Solaris 和LynxOS)的设计和他们用于实时系统的适用性上。实时操作系统需要的特性实时系统通常由多个异步执行线索实现。这是由响应外部事件,控制异步设备的需求确定的。由于这种特征,RTOS 必须支持多线程。并且,由于事件的重要性和发生频率是不同的,RTOS 必须支持优先级概念以便时间关键任务不会因为非时间关键任务延迟。此外,任务间需要通信,因此,OS 必须提供同步和通信功能。RTOS 还需要
22、支持计时相关功能比如高精度定时器和时钟。定时器用于支持周期处理并可以用来侦测系统超时错误。时钟用来跟踪时间。通常的实时应用可能需要知道微妙或者毫秒粒度的时间。考虑到性能的因素,操作系统必须是可预测的,并只增加最小的系统开销。正如先前讨论的,实时系统必须有确定的行为。这就意味着,所有操作的时间,包括操作系统功能,必须是确定的。为了达到确定,操作系统必须是可抢占的 preemptable,即如果 OS 正在处理低优先级的任务的请求,它必须能够停下正在做的工作并转移注意力到更高优先级的任务。这样就防止了高优先级任务被操作系统永久延迟的情况。SolarisSolaris 是一个通用 UNIX 操作系统
23、,运行于 SPARC 和 Pentium 系列 CPU。Solaris 拥有许多实时系统需要的特性【15】 。这些特性有: 多线程的优先的内核 A multithreaded preemptable kernel 全局优先级模型 global priority model:线程映射为轻量级进程,后者被分配优先级类 priority classes,然后进行全局调度 可配置的时钟 tick:时钟 tick 的频率可以改变,因此可以提高或降低调度器运行的频率 高精度的 POSIX 定时器:Solaris 定义了一个附加的基于硬件能力 POSIX 定时器(CLOCK_HIGHRES) ,能够提供具有
24、纳秒和毫秒精度的定时器。 优先级 I/O 流 priority I/O streams POSIX 实时 API 的附加支持: Solaris 8 现在支持 POSIX 1003.1b 的所有内容 对称多处理支持:Solaris 支持对用户透明的多处理。这就允许为实时处理保留处理器,增加了确定性。Solaris 线程实现Solaris 实现了用户级和内核级线程。用户级线程实现为一个用户应用级别的库,而内核级线程是内核看到的一个执行单元【16】 。Solaris 使用轻量级进程(LWP)机制在处理器上运行内核级线程。用户级线程到 LWP 的映射可以通过几种方法完成。如果多个用户级线程被映射到单个
25、内核级线程,那么同一时间他们之中最多只能有一个是活动的。为了发挥多处理器的优势,用户级线程可以被一一映射到 LWP。图一演示了如何设置 Solaris 处理器以及处理器绑定可以用于指定专为实时任务服务的处理器【15】 【17】 。先使用 psrset 命令,创建单个或多个处理器的池。注意,除了一个处理器之外,其他都是符合条件可以包含在处理器集中的;为了处理集合之外的轻量级进程需要一个处理器。然后使用 psradm 命令,屏蔽处理器集合中的处理器上未绑定的中断。再使用 psrset 命令,在绑定的处理器集合中的处理器上运行实时进程。所有其他非实时进程和中断运行在实时处理器集合之外的处理器上。后面
26、会提到,这种机制在实时处理及时性上有显著效果。Solaris 调度器为了支持不同类型的调度策略,Solaris 将每个轻量级进程运行于四个优先级类中的一个之中。这些类如表四所示【15】 。中断服务例程不是正在调度的进程的一部分,把他们包括在表中是因为他们运行于比所有任务优先级都高的优先级上,因此可能影响普通的 LWP处理。应用程序 LWP 运行于这三个类别中的一个:实时,系统或者分时。中断线程为不在中断服务程序中完成的中断处理而保留。表四 Solaris 优先级类类 优先级范围 描述ISRs N/A 异步中断服务例程,非调度的中断线程 160-269 不在 ISR 中完成的中断处理;基于 IS
27、R 的优先级调度实时 100-259 时间关键任务;固定优先级可抢占调度系统/内核 6099 系统级函数分时/交互 059 一般应用程序;OS 可能动态调整优先级以达到公平调度由两个过程组成:确定要运行哪个 LWP,执行 tick 处理【18】 。当调度器被调用时,就以最高全局优先级调度 LWP。如果机器拥有多个 CPU,调度器可以调度多个LWP。调度的第二个方面是 tick 处理,后者在每个时钟 tick 发生时都执行。调度器必须扫描所有活动的 LWP 并且更新他们的状态。对分时线程,如果调度器发现一个线程分享 CPU不够公平,可能增加该 LWP 的优先级。如果 LWP 拥有系统资源,Sol
28、aris 也可能提升其优先级到系统级别。因为实时线程按照固定优先级调度策略运行,他们之上的 tick 处理极少。LynxOSLynxOS 是为实时嵌入式系统开发的 UNIX 类型的操作系统。Lynx 内核是可抢占的preemptable,可重入的,最小 footprint 可达 97KB【19】 。Lynx 调度LynxOS 一种调度策略,256 个优先级的固定优先级可抢占 preemptive 调度。时钟 tick频率固定于 100Hz,即限制定时器精度为 10 毫秒。调度器在异步事件发生和系统状态改变时被调用。Lynx priority tracking。LynxOS 使用称为 prior
29、ity tracking 的机制操作不在 ISR 中完成的中断处理【20】 。这和 Solaris 使用的中断线程类形成了对比。使用中断线程类的问题是,为低优先级任务进行的中断处理将运行于比高优先级任务的应用处理更高的优先级。这会造成优先级翻转。LynxOS 解决该问题的办法是将中断处理的优先级联系到应用线程的优先级。256 个任务优先级再分为 512 个优先级,应用线程使用 256 个偶数优先级而中断线程使用 256 个奇数优先级。如图二所示,中断线程运行于比他们对应的应用中断高 half-step 的优先级上。中断线程作为设备的驱动程序的一部分为专门的设备编写,因此不和特定的应用线程相关。
30、出于这个原因,LynxOS 提供一种机制,设备驱动程序能够确定它正在为其运行的线程的优先级。用这个方法,中断线程可以调整其优先级到合适的级别。如果将来不同的应用线程需要相同的设备,中断线程可以改变其优先级。测试操作系统的实时性能这里使用的 benchmarks 分为两类:测量 OS 确定性的,测量某些特定的重要操作的延迟时间的。这些 benchmarks 提出的动机是前面讨论的实时性能需求。这些 benchmarks 测试核心操作系统能力,独立于任何真实的应用。同样,因为我们的兴趣在于确定最好的实时性能,所有实时线程都运行于最高实时优先级,benchmarks 使用的虚拟内存锁定在物理内存中。
31、表五概述了这里使用的 6 种 benchmarks。表五 实时 benchmarksBenchmarks 描述 测试方面 参数定时器抖动 创建一个周期线程,测量期望和实际到期时间之间的偏差测量 OS 响应时间 定时器周期:(1,10,100ms)响应 执行固定的处理负载,运行多次,测量执行时间确定线程是否能够以确定的方式响应处理类型:(添加,拷贝,whetstone )Bintime 调用 tod 时钟,测量两次调用的时间间隔测量最大内核 blocking时间无同步 测量线程到线程或者进程到进程同步的延迟时间测量线程间和进程间上下文切换时间信号量类型:(POSIX 有名 /无名信号量,pthr
32、ead 互斥量,lynx 信号量) ;进程到进程或者线程到线程消息传递 测量从线程到线程或者从进程到进程发送数据的延迟时间测量进程间和线程间可能的数据吞吐量数据 buffer 大小;进程到进程或者线程到线程实时信号 测量两个进程间实时信号的延迟时间测量 POSIX 实时信号的延迟时间无确定性 benchmarks表五中的前 3 个 benchmarks(定时器抖动 timer jitter,响应 response 和 bintime)被设计用来测试操作系统确定性【21】 。因为确定性意味着在所有环境下完成一个操作的时间都是确知的,我们通常只需要这些 benchmarks 的最坏情况时间。定时器
33、抖动测试的结构如图三所示。测试创建一个定时器,设置其在给定周期到期,然后确定真正到期时间。抖动定义为真正到期时间和期望到期时间之间的偏差。大多数现在的 CPU 都有一个 stamp counter,在每个 CPU 周期更新。大多数操作系统中的 POSIX 函数 clock_gettime 使用这个 stamp counter,可以给出高精度的 tod 时间。第二个确定性 benchmark(响应)测量 10 毫秒的固定操作的真正执行时间。计算一组每次单独执行的真正执行时间,确定应用响应时间是否是确定的。确定的操作由下面的三种不同操作中的一种的循环执行组成:添加(add) ,内存拷贝(copy)
34、或者 synthetic Whetstone benchmark(whet) 【22】 。最后一个确定性 benchmark( bintime)确定最大内核 blocking 时间。这个 benchmark使用一个最高优先级实时线程,重复调用 tod 时钟,计算每次调用需要的时间。每次调用需要的时间包括:执行系统调用的时间,内核 block 的时间。由于执行系统调用的时间应该是常数,benchmark 报告的最大时间和平均时间之间的偏差可以很好地指出内核中 block耗费的最大时间。延迟时间 benchmarks最后三个 benchmarks 测试操作系统的同步,消息传递和发送实时信号的能力。
35、对一个实时系统来说,使同步和通信延迟时间达到最小是很重要的。所以操作的平均延迟时间应该短小从而使总的系统开销最小化。限定最大延迟时间和实现确定性都很重要。图四列出了四个不同的同步测试。第一个测试中,一个单独的线程发送(signal S)然后等待(wait W)一个信号量。这个测试测量信号量系统调用的延迟时间。第二个测试使用信号量在两个线程之间发送。两个线程或者在单个进程中或者在两个不同进程中。系统开销在第一个测试中获得,第二个测试获得交替发送时间(roundtrip signaling time) ,从后者的一半时间中减去前者(系统调用开销)可以确定上下文切换时间。最后一个测试评估操作系统处理
36、优先级翻转的能力。这个测试使用信号量构建典型的优先级翻转情况(注:为清晰起见,图中没有画出信号量) 。在一个低优先级的任务获得(A)资源而之后高优先级任务也会需要该资源的情况下,优先级翻转就会发生。高优先级任务阻塞等待在该资源上,如果一个独立的中优先级任务独占 CPU 的话,高优先级任务会被不确定地延迟。这是一种优先级翻转,因为现在中优先级任务比高优先级任务更优先的处理。解决该问题的典型方法是允许低优先级任务继承高优先级任务的优先级以便前者能够运行然后释放(R)资源。这个测试中,中优先级任务使用一个固定时长的循环操作。如果发生了优先级翻转,那么低优先级任务获得资源的时刻和高优先级任务获得资源的
37、时刻之间的时间差至少是中优先级任务的固定时长操作的时间。如果 OS 同步机制防止了优先级翻转,上述时间差是极短可以忽略的。消息传递 benchmark 使用 POSIX 消息队列在同一进程或者不同进程中的两个线程中测量延迟时间和数据传输吞吐量。最后一个 benchmark 测量 POSIX 实时信号延迟时间。Benchmark 结果上节定义的 benchmarks 运行于两个不同的操作系统上:LynxOS 3.0.1 和 Solaris 8。表六列出了两个系统的细节。注意,两个平台的 CPU 是不同的。我们的 benchmarks 用来测量操作系统确定性,观察最坏情况时间,CPU 的差别几乎对
38、测试结果没有影响。不过,当比较平均时间的结果时应该考虑到 CPU 速度的差别。表六 试验平台平台 硬件 CPU(速度) 操作系统 CPU 配置Lynx Dell Pentium 2(266MHz) LynxOS 3.0.1 1 CPUSolaris(2 proc) Sun Ultra 60 SPARC(360MHz) Solaris 8 2 CPUsSolaris(1 proc) Sun Ultra 60 SPARC(360MHz) Solaris 8 1 CPUSolaris(1 rt) Sun Ultra 60 SPARC(360MHz) Solaris 8 2 CPUs, 1 CPU 保
39、留用来运行 RT benchmarks表六区分了三种不同的 Solaris 配置。这些不同配置可以让我们研究使用多个 CPU 的影响。第一种配置按照 Ultra 60 现状使用两颗 CPU。第二种配置中,其中一颗 CPU 被disable。最后一种配置,CPU 中的一颗专门保留,实时 benchmarks 运行于其上。这种配置下,保留的 CPU 可以不受未绑定的中断干扰。非实时的外部负载Benchmarks 是独立运行的,就是说,没有任何其他的用户进程在运行,从而不会引入非实时负载。通常实时系统会运行各种混合的应用,有些有实时要求有些没有。GUI 就是非实时应用的例子。表七列出了用于产生非实时
40、负载的处理的类型。负载包括 CPU 密集应用和使用中断 I/O 设备的应用,后者比如文件和网络子系统。表七 非实时(重)负载名字 描述 负载程度CPU 处理 Whetstone synthetic benchmark 产生的负载 10ms every 100msDisk 写文件操作 10ms every 100ms中断 外部串口中断 1000 interrupts/sec网络 TCP/IP socket transfers 4000 packets/sec系统调用 Sequence of utility system calls 10ms every 100msMemory Dynamic m
41、emory allocation 10ms every 100msFile search Search files in a directory and all sub-directories Continuous定时器抖动图五列出了所有平台的定时器抖动测试的结果。图五 A,没有负载的情况下,所有平台的抖动时间都在可接收的 200ms 下。Solaris (1rt)的抖动最小。 Lynx 的抖动也很低。图五 B,在重负载情况下,没有保留一个处理器的 Solaris 配置的抖动超过了限度。这些配置中,最坏情况的抖动达到了 10 秒之巨。应用响应表八列出了所有配置的最坏情况响应时间的结果。没有负载
42、的情况下,所有配置的响应结果都非常接近基准值 10 毫秒。有负载情况下只有 Lynx 和 Solaris(1 rt)配置接近 10毫秒。标准 Solaris 平台(Solaris 2proc)的最坏情况结果比标准值差了 3 个数量级。表八 最坏情况响应(毫秒)add copy Whet配置 无负载 重负载 无负载 重负载 无负载 重负载Lynx 9.9 9.9 10 10.1 10.1 10.2Solaris(2 procs) 10.1 11236.510.7 12061.7 10.6 12162.8Solaris(1 proc) 10.2 7310.7 10.2 4599.3 10.7 63
43、28.2Solaris(1 rt) 10 10 10 10 10.5 10.5Bintime图六显示所有配置的确定性 bintime benchmark 结果。无负载情况下,内核只有非常小的延迟。Solaris(1 rt)配置下,延迟小于 10 毫秒,其他配置下,延迟小于等于 100 毫秒。在重负载情况下,没有保留实时处理器的 Solaris 配置再次变得非常不确定。单颗 CPU 的Solaris 配置的最大延迟接近 1 秒。同步本节提供前面描述的同步测试的结果。测试 1(单线程内 signaling)图七演示了 Lynx 和 Solaris(1 rt)配置的简单同步测试的结果。Lynx 测试
44、了四种不同类型的同步机制,Solaris 测试了三种。如图七 A 所示,Solaris 平台的最坏情况延迟时间比Lynx 平台要好得多。两个平台上,增加负载对最坏情况时间几乎没有影响。图七 B 显示了同样的同步机制的平均延迟时间。 Lynx 信号量有最大的延迟时间,很可能因为该信号量实现了优先级继承。Solaris 的 POSIX 有名信号量延迟时间比其他机制的延迟时间都长得多,原因可能是信号量名字存放在文件系统中。测试二(线程间 signaling)图八显示了 Lynx 和 Solaris(1 rt)配置上的线程间 signaling 测试的结果。所有情况下平均和最坏情况交替时间 Lynx
45、都比 Solaris 好。更需要注意的是 Solaris 测试运行的处理器比 Lynx 测试运行的处理器还要快。图八也显示了所有类型的同步机制的延迟时间大致相同。测试三(优先级翻转)所有配置的优先级翻转测试结果在图九中显示。除了 Lynx(lsem)案例的所有案例中,低优先级和高优先级任务共享一个用于保护资源的 pthread 互斥量。没有负载的情况下,第一个 Lynx 配置的延迟时间与中优先级任务的延迟时间 10 毫秒有对应关系。这说明了一个事实,LynxOS 3.0.1 中,没有为 pthread 互斥量实现优先级继承。Lynx 信号量没有这个问题。Solaris 中实现了优先级继承,没有
46、负载情况下,所有 Solaris 配置的延迟时间都比较低。高负载情况下,只有 Lynx(lsem)和 Solaris(1 rt)配置显示了可接收的延迟时间。Solaris 1rt 和 2 proc 配置都受到了高负载的影响;因为缺乏优先级继承协议,Lynx 配置仍然具有高延迟时间。上下文切换时间。表九显示了所有平台的上下文切换时间,从头两个同步测试中的内存信号量结果计算而来。Lynx 上下文切换时间比最好的 Solaris 配置下的时间的一半还少。同样,Lynx 的进程到进程上下文切换时间只稍微比线程到线程切换时间长一点。表九 上下文切换时间无负载 重负载线程 进程 线程 进程配置 最大 平均
47、 最大 平均 最大 平均 最大 平均Lynx 42.2 20.1 47.2 24.2 40.5 20.1 53.2 24.0Solaris(1 rt) 65.4 52.9 446.8 49.9 67.2 51.8 461.0 50.6Solaris(1 proc) 198.9 53 459.1 50.3 160.8 53.2 23240 51.4Solaris(2 proc) 247.5 48.1 119.6 41.4 7149.0 68.7 639191 82.2Solaris 线程上下文切换时间比进程切换时间确定得多。 Solaris(1 rt)配置下,最大线程到线程切换时间接近平均值。然
48、而,同样配置下,进程到进程切换时间比平均值差了一个数量级。另一个有趣的发现是,Solaris 下进程间切换时间比线程间切换时间还稍微好一些。两种情况下,都存在 LWP 间的上下文切换,似乎说明了系统开销的 bulk 在调度器中。通信实时信号图十显示了所有配置下的实时信号 benchmark 结果。Lynx 配置比任何 Solaris 配置的信号延迟时间都小。并且,Solaris 1 proc 和 Solaris 2 proc 配置都被增加的非实时负载严重影响。消息队列所有配置的 POSIX 消息队列延迟时间和吞吐量在表十中显示。Lynx 平台的延迟时间比 Solaris 平台好,但是 Sola
49、ris 平台的吞吐量更好。后者更好的吞吐量可能是因为 Solaris平台上更快的硬件造成的。表十 POSIX 消息队列(无负载)延迟时间(usec) 吞度量(MB/sec)线程 进程 线程 进程配置 最坏 平均 最坏 平均 最坏 平均 最坏 平均Lynx 50.1 30.5 57.7 35.9 46.2 51.6 45.9 50.0Solaris(1 rt) 98.7 90.5 118.9 102.7 62.4 77.8 61.5 76.5Solaris(1 proc) 152.8 89.6 159 102.4 77.7 77.3 72.9 76.3Solaris(2 proc) 148.7 82.8 146.8 77.5 41.3 66.6 58.2 65.5适用性本文中我们已经评估过为实时嵌入式系统开发的软件中 POSIX 的使用情况。我们讨论了 POSIX 的特性以及这些特性在满足实时软件开发的需求方面做的如何。我们也实际评估了 LynxOS 3.0.1 和 Solaris 8 这两个 POSIX 的实现的实时性能特性。试验评估表明了 LynxOS 和 Solaris 可以适用于实时系统。LynxOS 的所有操作的系统开销比较低,即使在高负载条件下也是确定的。Solaris 8 包含了很多对实时开发很重要的特性,包括