>
首页 » 业界动态 » 实时操作系统到Linux系统的应用移植

实时操作系统到Linux系统的应用移植

作者:  时间:2008-05-20 09:22  来源:
  从一个操作系统到另一个操作系统的应用程序移植,即使在最好的情况下也经常是一个艰巨的任务。把一个实时的嵌入式应用程序移植到一个新的操作系统上,可以说是一项最困难的任务。为了帮助开发人员在不久的将来转移到嵌入式Linux上,或者将现有的应用程序运行在嵌入式Linux上这种投资的必要性,Jim 解释了这一转换的过程,评估了涉及到的困难和挑战,并且阐述了认识这种转换的益处。
  越来越多的公司正在转向嵌入式Linux,把它作为其下一代产品的操作系统。事实上,VDC的报告显示了嵌入式Linux占到32位和64位领域设计的三分之一,是其他所有嵌入式系统的2倍。
  一个典型的基于RTOS的应用程序依赖于很多因素,其中最重要的是编程/内存模型、API、性能,特别是实时响应的能力。另外一个重要的因素是软件开发环境。
编程模型
  几乎所有使用的RTOS有一个简单的编程模型,它由多线程的执行(通常称为“任务”)构成,包含在单一的地址空间中。举例来说,一个C语言的程序有一个单一的主函数,它创建所有其他的线程。每一个线程依次被定义为总程序中的一个C函数。不管是RTOS还是非保护内存中的应用程序,它们的物理地址和逻辑地址都是一样的。可能会有一些超级用户模式下的操作使用限制了在用户模式下的应用程序发出一些指令。基本上,所有的内存对应用程序来说都是虚拟的。
  在过去,大多数嵌入式处理器没有内存管理单元,因此RTOS单地址空间模式是必需的。然而今天大多数的中高端处理器配备了MMU,由MMU来管理内存。
  该体系结构的描述提出了一个移植RTOS代码到Linux上的简单架构:
  ◆ RTOS的全部应用代码移植到一个Linux单进程;
  ◆ RTOS的任务转换成Linux线程;
  ◆ RTOS的物理地址空间映射到Linux的虚拟地址空间。
  诸如VME机架的多板或多处理器架构,移植到一个多进程的Linux应用,如图1所示。

图1
构架上的考虑:进程和线程的创建
  是否使用遵循API的VxWorks和PSOS等RTOS仿真软件包,开发人员最终必须决定是否将线程或是进程作为执行RTOS的任务。在这点上,Linux内核对待线程和进程是同等的,都是以调度为目的的。然而不同的API创建和管理每个实体的类型、性能、资源的成本和益处都是关联的。
  通常来说,进程比线程大一点,因为它们传送更多的上下文信息。一个Linux线程的上下文如同RTOS的一个任务,主要由CPU寄存器、堆栈、当前的程序指针以及一些内核数据结构的入口组成。一个进程加上一个完整的虚拟地址空间。这样,至少内核必须创建和跟踪进程的页转换、所有代码的类型、上下文、数据等。对于重量级进程,上下文的主要影响有两点:创建的时间和相互的上下文切换时间。
  RTOS的代码会尽可能地争取要轻量级的执行。同样,当很多RTOS提供了动态的任务创建API时,其他以静态任务定义页表为特色,所有RTOS的商家不鼓励使用频繁的任务创建以节省时间和空间。Linux进程是重量级的,因为它们提供了更多的保护性和依赖性。
  这个熟悉的老式架构,因为简单,所以非常容易遭受破坏。正在运行的任务能够覆盖应用程序的代码和数据,还会写入外围设备的寄存器、破坏内核的数据结构、覆盖内核代码。任务的堆栈很容易发生溢出,并且一个接一个被覆盖掉,或者通过控制内存来破坏堆的顶部、其他数据或者附近的代码。
  从更高的层次来说,这种非正式有组织的、高度非遮掩的架构对代码质量提出了两个主要挑战:自身的失败机会,以及与主要事件再次失败的结合。
  当个别任务或者其他软件组件失败时,失败的原因几乎不可能被定位;甚至当检测到失败并且尝试恢复时,会以整个系统的失败而结束。监视代码不能够经常安全地重启任务,RTOS不能够恢复由失败任务动态定位的资源。结果就是复位通常是通过强制使用看门狗定时器来完成的,看门狗定时器重新启动整个系统或者软件引起的系统错误。
  通常,一个程序跑飞时没有任何征兆。一个错误的任务能够破坏在RTOS系统中任何地方的数据和代码。幸运的是,虽然这些破坏的影响瞬间产生,但是好像破坏的影响在几秒、几小时、几个月以后才会出现。
  当异常的征兆出现时,去联想预想不到的应用程序行为是极其困难的,这些行为由于原始的原因或者是很微小的,或者是破坏性的。
Linux编程模型的内部编译的可靠性
  Linux作为一个Unix兼容的操作系统,代表着一个更加强大的应用和系统编程模型。应用程序在它们受保护的地址空间内执行,因为它们之间的地址是相互不可见的;并且它们通过硬件的MMU来预防覆盖掉它们自己的代码,MMU出现在多数现代化的32/64位的处理器中。
  当共享Linux内核的虚拟地址空间时,它们不能覆盖内核代码或数据。既然进程不能够相互看到,也就不能相互破坏数据或代码。
API和实时库
  在开源标准以前,RTOS的制作者定义了他们自己的系统调用或API,这对每个RTOS的制作者来说都是独一无二的。接口函数是为流行的编程语言而提供的,诸如C、C++语言,这使得API函数对于使用高级语言的程序员是合适的。
  在过去的10年中,尽管只有POSIX规范的一部分与嵌入式应用程序相关,大多数的RTOS制作者还是给标准的POSIX提供了兼容库。很多客户使用他们自己的API集使本地RTOS接口分层以获得独立性和便捷性,而不是锁定成为一个私有的特殊版权的接口。
  开发人员使用标准的API建立应用程序来达到两个另外的目的:允许代码被移植成像Linux那样的标准操作系统;允许以后同样的代码在这样的一个环境下比使用私有的API更加容易移植。
  很多包括标准调用的商业RTOS以POSIX或者BSD来设定,但是那些API经常只存在于Windows下。特别是一个内核私有的API是最常被使用的,就是这些API锁定了项目到一个特殊的平台或者解决方案。
  如果开发人员正在移植标准的代码,或者考虑将哪个API运用到新的代码中,那么理解在Linux和其他操作系统中使用的最普遍的标准是非常重要的。
POSIX
  POSIX流行在基于Unix的开源系统中、政府和军事舞台,然而POSIX对于传统的嵌入式实时系统几乎没有影响。POSIX标准系列起源于美国国家标准与技术研究所,现在有被归入IEEE、IEEE1003和其他标准的预兆。在过去的10年中,POSIX经历了多次的修订,最近的一次是在2000年。兼容性和一致性是两个关于POSIX的重要观点。
  兼容性意味着一个特定的操作系统平台贯彻标准的一些子集,这种贯彻是备有文件证明的;甚至那些执行微小子集的平台能够兼容于POSIX标准。而一致性则代表更加严格的标准,意味着一个操作系统服从于过去的已证明测试。
SVR4、BSD和其他Unix的API
  SVR4和Unix的BSD版本是流行的系统标准,这些标准对于Linux的影响是巨大的。Linux贯彻了那些Unix API的大的子集(例如,对于共享内存、队列、信号量、BSD套接口和TCP/IP堆的Linux的ipc系统调用)。
  熟悉SVR4、BSD,或者像AIX、HPUX等其他通用的Unix的开发人员,对于Linux也能够很快掌握。
C语言库
  在嵌入式设计、RTOS或其他方面,很多API仅仅是标准C语言库,这些库或者是直接执行函数,或者是作为系统调用的包装。Linux有熟悉的libc/glibc,尽管尺寸很大,但易于理解。
  glibc的运行时间是对嵌入式应用程序内存尺寸的挑战。很多Linux的供应商为对于尺寸敏感的应用程序提供了经过裁剪的库。
RTOS接口层
  RTOS的核心是对于进程间通信调用的使用,这种调用提供了在任务中同步和通信的机制。表1提供了在典型的RTOS进程间通信调用和同等的Linux调用之间的映射总结。
表1

  尽管在RTOS的调用和同等的Linux调用之间的映射是直接的,但是移植的工作量会被增加,如果使用仿真库,这种仿真库为其他RTOS移植过来的Linux应用程序提供了同样的调用接口。
  对于Xenomai开源项目,这样的一个仿真技术是适用的。而这里,不同的仿真层提供给POSIX、VxWorks、VRTX和Itron这些被广泛使用的RTOS。注意,类似很多开源项目,Xenomai和它的外壳是正在进行的工作,它们可能还没有完成或者还要进行修改。不过,它代表了一个在移植过程中潜在的高价值的出发点。
  举个例子,POSIX模块主要是用来提供PSE51兼容的API。为了帮助移植其他PSE51兼容API的应用程序,它包含了一些对于POSIX规范的扩展。
  POSIX外壳已经包含了以下这些基本的特色: 线程、互斥量、信号量、条件变量、实时信号的支持、放弃和放弃处理、特殊线程数据、消息队列、定时器支持和共享内存。
  POSIX外壳创建实时线程,它们或是运行在Linux内核模块中,或者运行在用户空间的周期应用程序中。
  实时内核的API允许在内核和用户空间编程。开发人员通常更喜欢在用户空间编程,因为其间的延迟小,特别是在硬件上MMU的切换开销很小。目前为止,在用户空间编程比直接从内核空间运行应用程序更为容易。在用户空间编程带来了内存保护和在这个环境中调试实时应用程序的GNU调试器的支持。
实时性能
  对嵌入式应用程序来说,最重要的是满足实时的要求。对于设计RTOS,使得它们及时响应来满足实时的要求,并且测量RTOS的系统调用,已经做了相当大的努力,因此,开发人员能够确定系统的性能满足于实时的要求。RTOS的调用在一定意义上是循环的,应用程序和由RTOS提供的中断是同步的。因此,进行一个同步调用花费RTOS的时间是中断处理时间的一部分。
  2002年以前,Linux的实时性比较差,而它的吞吐量特别是在网络方面比较好。原因在于基本的Linux内核和Unix应用框架。这些系统被设计成在应用程序开销时,内核执行它所需要的。其原因就是如果开发人员知道内核不会被一个异常中断抢占,那么内核的代码就更容易编写。
  虽然这种方法被广泛应用于Unix和早期的Linux中,但是近来有一个下降的趋势,它降低了运行在多处理器体系的系统效率。同一时刻,非抢占式Linux使得Linux达到实时的标准变得困难,因为即使一个中断发生并且中断事件被调度运行,内核还会完成当前的任务。为了解决多处理器系统运行效率低的问题,Linux内核的开发人员开始侵入Linux内核的内部区域,使其非抢占区域变得更小,以至于更多的内核区域在多处理器系统上能够并行的执行并且完成得更好。
  那些对于改善Linux实时性有兴趣的人可以使用抢占的Linux内核来加速本地的实时响应。延迟减小到几百微秒到1毫秒之间。更多的性能提高包括缩短非抢占区域,以减小那些区域带来的任何延迟。
  自2002年以来,Linux已经支持实时应用程序。从那时起,Linux开发人员开始加强它的实时性能,标准Linux的实时性能在不断地提高。现在Linux的实时性能相当于大多数特有的实时内核。最近出现了对于Linux实时能力的重要推进,消耗CPU时间的同步机制的自旋锁被继承优先级互斥这种更可靠的同步机制替代了。互斥机制保证了CPU时间总是尽可能分配给优先级最高的应用程序,从而缩短了从中断到实时应用程序的过程。
  最后一个主要的实时Linux的改进是将中断处理作为一个应用程序的标准来执行。以前Linux的设计赋予中断处理比其他任何应用程序更高的优先级。通过把中断处理作为一个普通的应用程序处理,一旦优先级更高的应用程序可以抢占比它优先级低的中断处理程序。现在这些改变已经完成,性能和稳定性的改进使得Linux上的应用拥有与传统实时操作系统一样的快速和稳定。
迈步向前
  现在开发者正在放弃第一代实时操作系统,选择一个更稳定的、开放式的嵌入式平台,比如Linux。移植这些传统的系统代表着在挑战的同时,又提供了非常丰厚的投资回报。真正的风险不是放弃熟悉的环境、工具和API,而是当嵌入式系统开发不断前进时,它却停滞不前。遵循这篇文章概括的步骤和RTOS的移植技术, 开发人员可以付出最少的时间和精力,成功地将以前的RTOS代码移植到一个现代化的Linux平台上。

相关推荐

Linux将进军汽车智能系统领域

Linux  汽车智能系统  2013-07-09

Android回归Linux核心怀抱

Google  Linux  Android  2012-11-01

EXT4数据损失bug影响Linux稳定版内核

EXT4  Linux  2012-10-25

Fedora Linux 18 延期至年底

Fedora Linux 18  2012-10-17

Marvell和Tuxera推出业界最快的全功能NAS解决方案

Marvell  Linux  NAS  2012-01-19

ARM-Linux嵌入式系统的BootLoader分析与设计

嵌入式系统  Linux  2011-09-19
在线研讨会
焦点