访问电脑版页面

导航:老古开发网手机版其他

Linux嵌入式实时操作系统开发与设计(3)

导读:
关键字:
2.3 当前的实时操作系统

在这一节我们来看看一些操作系统的设计者是怎样来处理前一节所提到的问题的。

最简单的解决方案是改变分时的调度程序。一个例子是文献[12]介绍的系统。MINIX的round-robin调度器换为基于优先级的调度器。由于在MINIX中不使用页面调度和页面交换技术,假如对时间的响应不过分要求的话,这种方法是可以接受的。

一些在UNIX系统中采用POSIX.1b-1993实时标准规定的方式。这个标准规定了优先级调度,锁定用户程序页面,实时信号,改进的IPC和计时器,和别的一些特性。依从这些标准使UNIX更适合实时应用。

Linux是部分支持POSIX.1b标准的操作系统[12]。从1997年5月1日起,在Linux中完全实现了适合用于控制的调度器和内存锁定技术,定时器也部分实现。内核的不可占先,低的定时精度,和高的中断延迟仍然没有解决。因此,POSIX.1b兼容的Linux操作系统只适合一些软实时的处理。

别的满足POSIX.1b的操作系统是QNX[26]。QNX操作系统是微内核的操作系统。内核只是实现4种服务:进程调度,进程间通信,低级的网络通信,和中断分派。别的一些服务,比如说设备驱动程序和文件系统,实现为与用户进程协同操作的方式。这样系统内核非常小(大约7KB左右)而且非常快的。

QNX兼容POSIX 1003.1标准(编程接口)和POSIX 1003.2标准(外壳和应用程序)。对于熟悉UNIX的开发者来说,是非常方便的。QNX提供标准的UNIX部件:编译器,调试器,X-Windows,和TCP/IP。

微内核的设计比起传统的单块结构的设计有很多优势。调试用户程序比起调试内核模块更为简单。假如用户进程运行在单独的地址空间(像QNX那样),内存管理错误在不同模块是相互隔离的。驱动程序可以更获得多线程的好处。另外有良好的裁剪性。比如,QNX可以减少到100KB以下以适合ROM的大小,或者扩展到全功能的多机开发环境。移植和维护微内核的系统也更简单。缺点是微内核比起单块结构的内核来说不那么紧凑。

对于实时处理的微内核它提供了轻量级进程,快的上下文切换,和IPC。一个实时的用户进程可以中断设备驱动程序,在单块结构的内核是不可能的。由于微内核操作系统是非常小的,可以方便的计算最坏情况下的计时参数,比如中断延迟时间。

大多数的微内核操作系统的弱点是它的性能要差。微内核结构的操作系统在进程间通信和上下文交换有比较重的系统开销。微内核操作系统只提供简单的系统服务。因此,与单块结构的操作系统相比,完成相同的任务微内核操作系统要进行更多的系统调用。虽然一些研究者认为上下文切换,消息传递等可以高效地实现 [2],就性能而言,单块结构的操作系统仍然更成功。

一个单块结构的操作系统的例子是VxWorks[27]。VxWorks是专有的实时操作系统,采用主机/目标机方式。一个UNIX主机用来软件的开发和运行程序的非实时部分。一个叫wind的VxWorks内核在目标机上运行实时任务。机器间的通信使用TCP/IP网络连接。

虽然VxWorks不兼容UNIX系统,它提供了一些符合POSIX接口规范的函数,特别是POSIX.1b实时扩展部分。大多数的VxWorks API是专有的。

在VxWorks中,内核和任务运行在同一个地址空间。这样,任务间的切换非常快,和省去了必要的系统调用开销。一个实时连接器允许动态的装载任务和系统模块。这些特性使系统具有好的伸缩性。一个交互式的类似C语法的shell用来检查和改变参数值,计算表达式,调用函数,和进行简单的调试。这个特性使得开发更为简单方便。内核和任务运行在同一个地址空间也使得系统更脆弱,一个模块的错误更容易影响到别的模块。

REAL/IX操作系统也是单块结构。这是一个有完全UNIX特性的操作系统,原自于UNIX System V,改造使它拥有实时处理能力。它的内核是完全可占先的。它通过内核信号量来实现,提供互斥方式访问系统资源,比起传统的sleep/wakeup函数和关中断来说,这种方式更优秀。使用信号量代替关中断降低了中断延迟时间,也使的移植到多处理器系统更为容易。

REAL/IX是POSIX.1003兼容的操作系统。这个特性使得移植UNIX应用程序更为容易。除实时调度以外,实时能力还包括预先分配内存和文件空间,同步与非同步I/O,增强的IPC和计时器,可连接的中断。最后的特性允许用户进程处理中断。

现在有一个趋向于使用Windows NT来支持实时处理。只要原因是兼容先前的Windows,因此,可以使用先前的应用程序。也是指望用一个操作系统来做任何事情:办公应用,服务,和实时控制。用一个操作系统可以减少人员培训的开销。程序员可以用到广泛的Win32 API。Microsoft对市场的垄断也是一个原因。

像文献[25]指出的那样,Windows NT的内核并不适合硬实时的处理:Win32 API不是设计用来实时应用的,中断处理的方式可能引起一个不确定的延迟,而且对于嵌入式系统来说,Windows NT对内存的要求也是一个问题。

Microsoft为了处理上面提到的一些问题。开发了Windows CE嵌入式实时操作系统,Windows CE内核支持按优先级抢占的方式调度多任务。Windows CE可以固化到ROM中,从ROM起动,使用时对内存RAM要求不高。Windows CE将中断分为两个步骤:第一步是执行中断服务子程序ISR(interrupt service routine);第二步为中断服务线程IST(interrupt service thread)。内核使中断处理程序执行尽可能短,大部分处理放在IST中,可以把最高优先级安排给中断服务线程,以保证IST尽快运行而不会被占先。其与Win32 API兼容的编程接口方便熟悉Windows的程序员开发和移植Windows应用。


第三章 嵌入式实时LINUX系统RTLINUX的设计与实现

从上一章的分析,我们已经知道Linux是一个通用操作系统,将它应用于嵌入式实时环境有许多缺点和不足。特别是在运行内核线程时,Linux关闭中断,别的问题包括分时的调度,虚拟文件系统的时间不确定性,缺乏高精度的计时器。所以要对现有的Linux进行改造,即要对Linux进行实时化,这一章将介绍RTLinux的结构和如何对RTLinux进行实时化。

3.1 RTLinux的结构

RTLinux使用众所周知的虚拟机技术的简单方案来解决这些相互对立的解决上面提到的问题。增加了一个仿真程序来替换Linux的底层中断程序。一个小的实时内核与Linux内核共享控制处理器。如果来自硬件的属于实时内核的中断将直接被处理,属于Linux内核的中断通过中断仿真程序处理。假如Linux内核中断请求没有被允许,中断模拟程序将在中断队列中标记这次中断的发生。当Linux内核的中断请求被允许时,在中断队列中的中断将被执行。因此,实时内核的操作可以得到机器的立即相应,而且Linux内核不能延迟实时任务的执行。实时任务与运行在Linux内核中的进程之间的通讯通过 FIFOs与共享内存的方式进行。使用实时内核中的调度器调度实时任务,调度器的算法和策略可以用户自己定义;而系统也已经实现了RMS和EDF算法。

这样就保留了Linux操作系统所提供的丰富的功能,而且改动它使其作为一个基本内核与实时内核共享控制CPU。实际上,系统可以看作具有双内核的操作系统,实时内核拥有更高优先级别的任务,换句话说,基本内核可以看作实时系统的空闲任务:只是在没有实时处理要求的时候运行。这样实现的 RTLinux的详细结构图如图3.1所示。


3.2 中断模拟

要在标准Linux上增加硬实时能力,首先遇到的一个问题是Linux为了达到同步使用关中断的方式。混杂在一块的关和开中断操作(i486处理器的cli和sti机器指令)造成不可确定的中断分派延迟。Linux内核是一整块大的内核。在提供系统服务各个部分之间没有一个保护的分界线。要改写 Linux内核感到非常棘手。造成要限定关中断的时间非常困难,当更新版本发行时,也可能变得不正确。即使我们能处理这些,时间上离我们的要求仍然太长。

在实时Linux中,是通过在Linux内核与中断控制硬件之间增加一个模拟软件,这是与文献[6]相似的技术,但是用于不同的目的。在 Linux源代码中所有的cli,sti,和iret(iret:中断返回指令)被替换为相应的宏:S_CLI,S_STI和S_IRET。所有的硬件中断指令都被中断模拟器捕捉。

/* These are macros */

S_CLI: movl , SFIF

S_IRET: push %ds

pushl %eax

pushl %edx

movl $KERNEL_DS, %edx

mov %dx, %ds

cli

movl SFREQ, %edx

andl SFMASK, %edx

bsrl %edx, %eax

jz not_found

movl , SFIF

sti

jmp SFIDT ( , %eax, 4)

not_fount:

movl , SFIF

sti

popl %edx

popl %eax

pop %ds

iret

S_STI: pushfl

pushl $KERNEL_CS

pushl $done_STI

S_IRET

done_STI:

程序3.1 “软”cli,sti和iret

关中断发生时,在模拟器的一个变量重新设定。只要中断发生,模拟器将检查这个变量。假如这个值是已经设定(Linux中断是允许的),Linux 的中断处理程序将立即调用。如果Linux中断是不允许的,中断处理程序将不会被调用。一个变量值将设定,并且保存所有挂起的中断的信息。一旦Linux 中断允许处理时,所有挂起的中断将被处理。这种中断称之为软中断。

由于Linux不能直接控制中断控制器,Linux的中断不会影响实时中断的处理。

S_CLI、S_STI和S_IRET宏如程序3.1所示。这个代码使用GNU汇编规范。S_CLI宏简单重新设定变量值,保存Linux中断状态。S_STI宏设置正在被处理的中断的栈。S_IRET宏模拟中断返回。S_IRET宏的工作就像硬件iret指令所做的那样允许软中断。

S_IRET宏是三个宏中最有意思的一个。它先保存一些寄存器和初始化指向内核的数据段寄存器。然后存取全局变量。扫描所有挂起的中断而设置的屏蔽位。如果没有发现挂起的中断,设置中断状态变量,一个硬件的中断返回指令被执行。如果发现一个中断,跳转到Linux中断处理程序。中断处理程序返回后,依次跳转到下一个未处理中断的中断处理程序,直到没有中断再挂起为止。

扫描和转到中断处理程序是一个原子操作,否则,在这过程中有一个中断发生扫描将不能发现任何挂起的中断,这个新到的中断的处理程序将会延迟处理,直到下一个S_STI或者S_IRET被执行是才能被处理。

使用链式跳转的方式来代替子程序调用的方式调用Linux中断处理程序,是因为后者不能完全模拟直接的中断处理。Linux中断处理程序检查栈来发现是用户还是内核代码被中断,基于这个做出决定处理。因此,保护中断状态是很重要的。

来源:   作者:  2006/9/25 16:50:53
栏目: [ ]

相关阅读

安森美推出新的高功率图腾柱PFC控制器,满足具挑战的能效标准

动态功耗低至60μA/MHz!助力设备超长续航,首选国民技术低功耗MCU!