嵌入式操作系统介绍分析
嵌入式操作系统介绍分析
嵌入式操作系统介绍分析
一,各种嵌入式操作系统介绍
1.uC/OS-II
u C / OS
是一种免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统。
μC/OS-II
的前身是 μC/OS ,最早出自于 1992 年美国嵌入式系统专家 Jean J.Labrosse 在《嵌入式系统编程》杂志的 5 月和 6 月刊上刊登的文章连载,并把 μC/OS 的源码发布在该杂志的 BBS 上。
μC/OS
和 μC/OS-II 是专门为计算机的嵌入式应用设计的, 绝大部分代码是用 C 语言编写的。 CPU 硬件相关部分是用汇编语言编写的、总量约 200 行的汇编语言部分被压缩到最低限度,为的是便于移植到任何一种其它的 CPU 上。用户只要有标准的 ANSI 的 C 交叉编译器,有汇编器、连接器等软件工具,就可以将 μC/OS-II 嵌人到开发的产品中。 μC/OS-II 具有执行效率高、占用空间小、实时性能优良和可扩展性强等特点, 最小内核可编译至 2KB 。 μC/OS-II 已经移植到了几乎所有知名的 CPU 上。
严格地说 uC/OS-II 只是一个实时操作系统内核,它仅仅包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。 没有提供输入输出管理,文件系统,网络等额外的服务。但由于 uC/OS-II 良好的可扩展性和源码开放,这些非必须的功能完全可以由用户自己根据需要分别实现。
uC/OS-II
目标是实现一个基于优先级调度的抢占式的实时内核,并在这个内核之上提供最基本的系统服务,如信号量,邮箱,消息队列,内存管理,中断管理等。
任务管理
uC/OS-II
中最多可以支持 64 个任务,分别对应优先级 0 ~ 63 ,其中 0 为最高优先级。 63 为最低级,系统保留了 4 个最高优先级的任务和 4 个最低优先级的任务,所有用户可以使用的任务数有 56 个。
uC/OS-II
提供了任务管理的各种函数调用,包括创建任务,删除任务,改变任务的优先级,任务挂起和恢复等。
系统初始化时会自动产生两个任务:一个是空闲任务,它的优先级最低,该任务仅给一个整形变量做累加运算;另一个是系统任务,它的优先级为次低,该任务负责统计当前 cpu 的利用率。
时间管理
uC/OS-II
的时间管理是通过定时中断来实现的,该定时中断一般为 10 毫秒或 100 毫秒发生一次,时间频率取决于用户对硬件系统的定时器编程来实现。中断发生的时间间隔是固定不变的,该中断也成为一个时钟节拍。
uC/OS-II
要求用户在定时中断的服务程序中,调用系统提供的与时钟节拍相关的系统函数,例如中断级的任务切换函数,系统时间函数。
内存管理
在 ANSI C 中是使用 malloc 和 free 两个函数来动态分配和释放内存。但在嵌入式实时系统中,多次这样的错作会导致内存碎片,且由于内存管理算法的原因, malloc 和 free 的执行时间也是不确定。
uC/OS -II
中把连续的大快内存按分区管理。每个分区中包含整数个大小相同的内存块,但不同分区之间的内存快大小可以不同。用户需要动态分配内存时,系统选择一个适当的分区,按块来分配内存。释放内存时将该块放回它以前所属的分区,这样能有效解决碎片问题,同时执行时间也是固定的。
任务间通信与同步
对一个多任务的操作系统来说,任务间的通信和同步是必不可少的。 uC/OS-II 中提供了 4 中同步对象,分别是信号量,邮箱,消息队列和事件。所有这些同步对象都有创建,等待,发送,查询的接口用于实现进程间的通信和同步。
任务调度
uC/OS-II
采用的是可剥夺型实时多任务内核。可剥夺型的实时内核在任何时候都运行就绪了的最高优先级的任务。
uC/os-II
的任务调度是完全基于任务优先级的抢占式调度,也就是最高优先级的任务一旦处于就绪状态,则立即抢占正在运行的低优先级任务的处理器资源。为了简化系统设计, uC/OS-II 规定所有任务的优先级不同,因为任务的优先级也同时唯一标志了该任务本身。
任务调度将在以下情况下发生:
1
) 高优先级的任务因为需要某种临界资源,主动请求挂起,让出处理器,此时将调度就绪状态的低优先级任务获得执行,这种调度也称为任务级的上下文切换。
2
) 高优先级的任务因为时钟节拍到来,在时钟中断的处理程序中,内核发现高优先级任务获得了执行条件 ( 如休眠的时钟到时 ) ,则在中断态直接切换到高优先级任务执行。这种调度也称为中断级的上下文切换。
这两种调度方式在 uC/OS-II 的执行过程中非常普遍,一般来说前者发生在系统服务中,后者发生在时钟中断的服务程序中。
调度工作的内容可以分为两部分:最高优先级任务的寻找和任务切换。其最高优先级任务的寻找是通过建立就绪任务表来实现的。 u C / O S 中的每一个任务都有独立的堆栈空间,并有一个称为任务控制块 TCB(Task Control Block) 的数据结构,其中第一个成员变量就是保存的任务堆栈指针。任务调度模块首先用变量 OSTCBHighRdy 记录当前最高级就绪任务的 TCB 地址,然后调用 OS_TASK_SW() 函数来进行任务切换。
μC/OS-II
的组成部分
μC/OS-II
可以大致分成核心、任务处理、时间处理、任务同步与通信, CPU 的移植等 5 个部分。
核心部分 (OSCore.c)
是操作系统的处理核心,包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。能够维持系统基本工作的部分都在这里。
任务处理部分 (OSTask.c)
任务处理部分中的内容都是与任务的操作密切相关的。包括任务的建立、删除、挂起、恢复等等。因为 μC/OS-II 是以任务为基本单位调度的,所以这部分内容也相当重要。
时钟部分 (OSTime.c)
μC/OS-II
中的最小时钟单位是 timetick (时钟节拍)。任务延时等操作是在这里完成的。
任务同步和通信部分
为事件处理部分,包括信号量、邮箱、邮箱队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。
与 CPU 的接口部分
是 指 μC/OS-II 针对所使用的 CPU 的移植部分。由于 μC/OS-II 是一个通用性的操作系统,所以对于关键问题上的实现,还是需要根据具体 CPU 的具体内容和要求作相应的移植。这部分内容由于牵涉到 SP 等系统指针,所以通常用汇编语言编写。主要包括中断级任务切换的底层实现、任务级任务切换的底层实现、时钟节拍的产生和处理、中断的相关处理部分等内容 .
2.Nucleus
NucleusPLUS
嵌入式操作系统是目前最受欢迎的操作系统之一。 NucleusPLUS 是为实时嵌入式应用而设计的一个抢先式多任务操作系统内核,其 95 %的代码是用 ANSI C 写成的,因此非常便于移植并能够支持大多数类型的处理器。从实现角度来看, NucleusPLUS 是一组 C 函数库,应用程序代码与核心函数库连接在一起,生成一个目标代码,下载到目标板的 RAM 中或直接烧录到目标板的 ROM 中执行。在典型的目标环境中, NucleusPLUS 核心代码区一般不超过 20K 字节大小。 NucleusPLUS 采用了软件组件的方法,每个组件具有单一而明确的目的,通常由几个 C 及汇编语言模块构成,提供清晰的外部接口,对组件的引用就是通过这些接口完成的。除了少数一些特殊情况外,不允许从外部对组件内的全局进行访问。由于采用了软件组件的方法, NucleusPLUS 各个组件非常易于替换和复用。 NucleusPLUS 的组件包括任务控制、内存管理、任务间通信、任务的同步与互斥、中断管理、定时器及 I/O 驱动等。
Nucleus
具有如下特点
1
、提供源代码。 NucleusPLUS 提供注释严格的 C 源级代码给每一个用户。这样,用户能够深入地了解底层内核的运作方式,并可根据自己的特殊要求删减或改动系统软件,这对软件的规范化管理及系统软件的测试都有极大的帮助。另外,由于提供了 RTOS 的源级代码,用户不但可以进行 RTOS 的学习和研究,而且产品在量产时也不必支付 License ,可以省去大量的费用。对于军方来说,由于提供了源代码,用户完全可以控制内核而不必担心操作系统中可能会存在异常任务导致系统崩溃。
2
、性价比高。 NucleusPLUS 由于采用了先进的微内核 (Micro- kernel) 技术,因而在优先级安排,任务调度,任务切换等各个方面都有相当大的优势。另外,对 C++ 语言的全面支持又使得 NucleusPLUS 的 Kernel 成为名副其实的面向对象的实时操作系统内核。然而,其价格却比较合理。所以,容易被广大的研发单位接受。
3
、易学易用。 NucleusPLUS 能够结合 Paradigm , SDS 以及 ATI 自己的多任务调试器组成功能强大的集成开发环境,配合相应的编译器和动态联结库以及各类底层驱动软件,用户可以轻松地进行 RTOS 的开发和调试。另外,由于这些集成开发环境 (IDE) 为所有的开发工程师所熟悉,因而,容易学习和使用。
4
、功能模块丰富。 NucleusPLUS 除提供功能强大的内核操作系统外,还提供种类丰富的功能模块。例如用于通讯系统的局域和广域网络模块,支持图形应用的实时化 Windows 模块,支持 Internet 网的 WEB 产品模块,工控机实时 BIOS 模块,图形化用户接口以及应用软件性能分析模块等。用户可以根据自己的应用来选择不同的应用模块。
NucleusPLUS
的多种支持
NucleusPLUS
的 RTOS 内核可支持如下类型的 CPU : x86,68xxx,68HCxx,NECV25, oldFire,29K,i960,MIPS,SPARClite,TIDSP,ARM6/7,StrongARM, H8/300H,SH 1/2/3 ,owerPC,V8xx,Tricore,Mcore,PanasonicMN10200,Tricore,Mcore 等。可以说 NUCLEUS+ 是支持 CPU 类型最丰富的实时多任务操作系统。针对各种嵌入式应用, NucleusPLUS 还提供相应的网络协议(如 TCP/IP , SNMP 等),以满足用户对通讯系统的开发要求。
另外,可重入的文件系统、可重入的 C 函数库以及图形化界面等也给开发者提供了方便。针对不同的 CPU 类型, Nucleus 还提供编译器、动态连接库、多任务调试器等相应的工具来配置用户的开发环境。值得提出的是 ATI 公司最近还发表了基于 Microsoft Developers Studio 的嵌入式集成开发环境- NUCLEUSEDE 。从而率先将嵌入式开发工具与 Microsoft 的强大开发环境结合起来,提供给工程师们强大的开发手段。
三、源代码带来的优势众所周知, Nucleus 实时多任务操作系统提供给用户源代码。这除商务上给用户带来巨大益处(免交 Royalty )外,还在技术方面给用户极大的方便,即无需编写和调试 BSP ,从而达到易学易用的目的,加速产品上市。对 RTOS 有一定知识的工程师一定清楚,使用 RTOS 最大的障碍在于编写和调试 BSP 。大家知道,在调试目标系统的软件之前,必须将目标与主机连接起来并建立通讯。为此,我们可以编写一段监控程序( Monitor )。然而,如果要调试基于 RTOS 内核的程序,主机上的调试器( Debugger )除要与目标建立通讯外,更重要的是必须识别 RTOS 的任务,这样才能进行任务级调试( Task-awareDebugger )。因此,只有 Monitor 是不够的。如果我们选用的 RTOS 不提供源代码,那么,主机上的调试器( Debugger )就只有通过用户编写的 BSP 来了解 Kernel 在现有硬件平台上对各个任务进行调度的情况。显然,编写 BSP 必须对 CPU 目标系统的硬件以及应用软件等有全面而深入的了解。一般说来,对于一个有一定硬件开发经验的工程师来说,编写一个新的 BSP 要花的平均时间为两个月左右。这对于一个新手来说可是比较困难的。对于编写 BSP 的工程师来说,另外一个更大的挑战就是如何调试 BSP ,即如何验证所编写的 BSP 是否正确。通常刚刚焊接安装好的 PCB 板中,硬件或软件的故障( Bugs )是比较多的。甚至更常见的是 CPU 部分都没有运作正常。有时时序错误和总线错误都还存在。在您把写好的 BSP 烧入 EPROM (或 FLASH )中试图将目标与主机建立联系时,您几乎 100% 地会发现根本无法通讯,眼前一团漆黑,不知是软件有错误还是硬件不运转。 BSP 在正常运行吗?不得而知。在焦急和摸索中您可能发现几个月已悄然而过。对于早期的实时操作系统来说, BSP 是必由之路。然而,新一代的 RTOS-NucleusPLUS 则避免了 BSP 带来的痛苦过程。因为 Nucleus 的调试是基于全新的动态连接库( DLL )。用户只须通过监控程序( Monitor )或者 BDM 调试口(或者 JTAG 调试口)建立目标系统( Target )与主机( Host )之间的通讯,并给主机上的 Debugger 初始化特性中加入 Nucleus 的动态连接库( DLLs ),这时,调试器就能够自动地去识别运行在目标系统中的 Nucleus 内核和各个应用任务,从而完成任务级调试。上述的动态连接库( DLLs )是由 RTOS 厂商和 Debugger 厂商合作完成的,用户无须自行编写。因此, Nucleus 的用户只需要将精力放在基于 Nucleus 的编程工作中。对于一个新手,往往经过一天到两天的学习和培训,就可以投入到应用程序编制工作中去,无需花大量的时间去研究 CPU ,特定的硬件等。另外,由于有了源程序,用户在调试程序时可以清楚地通过 STEPINTO 命令,追踪到 RTOS 的内层中去,观看和学习 Kernel 对任务的管理和调度机制。对于有志研究 RTOS 深层技术的工程师来说极为方便。对于 Motorola68K 和 PowerPC ,用户可以利用 GreenHill 公司的 Mutil 调试器或 TRACE-ICD 来完成 NucleusPLUS 的调试;对于 ARM 和 StrongARM ,用户可以利用 ARM 公司的 SDT251 调试器或 TRACE-ICD 来完成 NucleusPLUS 的调试;对于 Intelx86 实模式,用户可以利用 Paradigm 公司的调试器及其 DLL 来进行任务级调试;对于 Intelx86 保护模式则可以利用 SSI 公司 Softprobe 调试器和 SSIDLL 来调试;对于 i960 , SH3/4 , ARM6/7 , MIPS 等芯片,则可以使用 ATI 公司自己的 UDB 调试器来进行任务的调试。结论:动态连接库( DLL )是在 RTOS 工具中新出现的应用趋势,通过这种方式,用户可以免去 BSP 带来的麻烦,灵活方便地进行开发和调试,大大加速开发进度。 Nucleus 实时操作系统提供源代码,支持丰富的 CPU 种类,配合各类 DLL 动态连接库,为使用和研究 RTOS 技术的工程带来极大的利益。
3.ThreadX
ThreadX
是优秀的硬实时操作系统 (RTOS) ,适用于深嵌入式应用中,具有规模小、实时性强、可靠性高、无产品版权费、易于使用等特点,并且支持大量的处理器和 SoC ,包括 ARM 、 PowerPC 、 SH 4 、 MIPS 、 ADI DSP 、 TI DPS 、 Nios II 等,因此广泛应用于消费电子、汽车电子、工业自动化、网络解决方案、军事与航空航天等领域中。
下面是 ThreadX 的应用实例:
2005
年 7 月 4 日
,美国国家航空航天局( NASA )成功实施了“深度撞击”飞船对坦普尔 1 号彗星的准确撞击,其中, ThreadX 在其中发挥了关键作用,控制其中全部三套彗星成像仪的运行;
惠普公司的多款数码相机中应用了 ThreadX RTOS 和配套的 FileX 文件系统组件,同时,惠普公司也在全系列打印机产品中使用了 ThreadX RTOS ;
ThreadX
成功应用于 Panasonic 公司的 11Mbs 无线网卡;
在 Konica-Minolta 、 Toshiba 、 Ricoh 、 Samsung 等公司的数码产品中, ThreadX 得到了广泛的应用;
据 CMP 统计表明, ThreadX RTOS 已经占有全球第三大硬实时操作系统市场份额;
TreadX
支持的 CPU 有: PowerPC,680x0/683xx,ColdFile,ARM7,ARM/Thumb ,MCORE, ARC, TriCore, X86,StrongARM,MIPS,SH,I960,V8xx,SPARC,Xscale, H8/300H, TMS 320C .
4. uClinux
Linux
是一种很受欢迎的操作系统,它与 UNIX 系统兼容,开放源代码。它原本被设计为桌面系统,现在广泛应用于服务器领域。而更大的影响在于它正逐渐地应用于嵌入式设备。 uClinux 正是在这种氛围下产生的。在 uClinux 这个英文单词中 u 表示 Micro ,小的意思, C 表示 Control ,控制的意思,所以 uClinux 就是 Micro-Control-Linux ,字面上的理解就是 " 针对微控制领域而设计的 Linux 系统 " 。
4.1 uClinux
的小型化方法
标准 Linux 可能采用的小型化方法
重新编译内核
Linux
内核采用模块化的设计,即很多功能块可以独立的加上或卸下,开发人员在设计内核时把这些内核模块作为可选的选项,可以在编译系统内核时指定。因 此一种较通用的做法是对 Linux 内核重新编译,在编译时仔细的选择嵌入式设备所需要的功能支持模块,同时删除不需要的功能。通过对内核的重新配置,可以 使系统运行所需要的内核显著减小,从而缩减资源使用量。
制作 root 文件系统映象
Linux
系统在启动时必须加载根( root )文件系统,因此剪裁系统同时包括 root file system 的剪裁。在 x86 系统下, Linux 可以在 Dos 下,使用 Loadlin 文件加载启动。
uClinux
采用的小型化方法
1.
uClinux
的内核加载方式
uClinux
的内核有两种可选的运行方式:可以在 flash 上直接运行,也可以加载到内存中运行。这种做法可以减少内存需要。
Flash
运行方式:把内核的可执行映象烧写到 flash 上,系统启动时从 flash 的某个地址开始逐句执行。这种方法实际上是很多嵌入式系统采用的方法。
内核加载方式:把内核的压缩文件存放在 flash 上,系统启动时读取压缩文件在内存里解压,然后开始执行,这种方式相对复杂一些,但是运行速度可能更快( ram 的存取速率要比 flash 高)。同时这也是标准 Linux 系统采用的启动方式。
2.
uClinux
的根( root )文件系统
uClinux
系统采用 romfs 文件系统,这种文件系统相对于一般的 ext2 文件系统要求更少的空间。空间的节约来自于两个方面,首先内核支持 romfs 文件系统比支持 ext2 文件系统需要更少的代码,其次 romfs 文件系统相对简单,在建立文件系统超级块( superblock )需要更少的存储空间。 Romfs 文件系统不支持动态擦写保存,对于系统需要动态保存的数据采用虚拟 ram 盘的方法进行处理( ram 盘将采用 ext2 文件系统)。
3.
uClinux
的应用程序库
uClinux
小型化的另一个做法是重写了应用程序库,相对于越来越大且越来越全的 glibc 库, uClibc 对 libc 做了精简。
uClinux
对用户程序采用静态连接的形式,这种做法会使应用程序变大,但是基于内存管理的问题,不得不这样做(这将在下文对 uClinux 内存管理展开分析时进行说明),同时这种做法也更接近于通常嵌入式系统的做法。
4.2 uClinux
的开发环境
GNU 开发套件
Gnu
开发套件作为通用的 Linux 开放套件,包括一系列的开发调试工具。主要组件:
Gcc
: 编译器,可以做成交叉编译的形式,即在宿主机上开发编译目标上可运行的二进制文件。
Binutils
:一些辅助工具,包括 objdump (可以反编译二进制文件), as (汇编编译器), ld (连接器)等等。
Gdb
:调试器,可使用多种交叉调试方式, gdb-bdm (背景调试工具), gdbserver (使用以太网络调试)。
uClinux
的打印终端
通常情况下, uClinux 的默认终端是串口,内核在启动时所有的信息都打印到串口终端(使用 printk 函数打印),同时也可以通过串口终端与系统交互。
uClinux
在启动时启动了 telnetd (远程登录服务),操作者可以远程登录上系统,从而控制系统的运行。至于是否允许远程登录可以通过烧写 romfs 文件系统时有用户决定是否启动远程登录服务。
交叉编译调试工具
支持一种新的处理器,必须具备一些编译,汇编工具,使用这些工具可以形成可运行于这种处理器的二进制文件。对于内核使用的编译工具同应用程序使用的有所不同。在解释不同点之前,需要对 gcc 连接做一些说明:
.ld
( link description )文件: ld 文件是指出连接时内存映象格式的文件。
crt0.S
:应用程序编译连接时需要的启动文件,主要是初始化应用程序栈。
pic
: position independence code ,与位置无关的二进制格式文件,在程序段中必须包括 reloc 段,从而使的代码加载时可以进行重新定位。
内核编译连接时,使用 ucsimm.ld 文件,形成可执行文件映象,所形成的代码段既可以使用间接寻址方式(即使用 reloc 段进行寻址),也可以使用绝对寻址方式。这样可以给编译器更多的优化空间。因为内核可能使用绝对寻址,所以内核加载到的内存地址空间必须与 ld 文件中给定的内存空间完全相同。
应用程序的连接与内核连接方式不同。应用程序由内核加载(可执行文件加载器将在后面讨论),由于应用程序的 ld 文件给出的内存空间与应用程序实际被加载的 内存位置可能不同,这样在应用程序加载的过程中需要一个重新地位的过程,即对 reloc 段进行修正,使得程序进行间接寻址时不至于出错。(这个问题在 i386 等高级处理器上方法有所不同,本文将在后面进一步分析)。
由上述讨论,至少需要两套编译连接工具。在讨论过 uClinux 的内存管理后本文将给出整个系统的工作流程以及系统在 flash 和 ram 中的空间分布。
可执行文件格式
先对一些名词作一些说明:
coff
( common object file format ):一种通用的对象文件格式
elf
( excutive linked file ):一种为 Linux 系统所采用的通用文件格式,支持动态连接
flat
: elf 格式有很大的文件头, flat 文件对文件头和一些段信息做了简化
uClinux
系统使用 flat 可执行文件格式, gcc 的编译器不能直接形成这种文件格式,但是可以形成 coff 或 elf 格式的可执行文件,这两种文件需要 coff2flt 或 elf2flt 工具进行格式转化,形成 flat 文件。
当用户执行一个应用时,内核的执行文件加载器将对 flat 文件进行进一步处理,主要是对 reloc 段进行修正(可执行文件加载器的详见 fs/binfmt_flat.c )。以下对 reloc 段进一步讨论
需要 reloc 段的根本原因是,程序在连接时连接器所假定的程序运行空间与实际程序加载到的内存空间不同。假如有这样一条指令:
jsr app_start;
这一条指令采用直接寻址,跳转到 app_start 地址处执行,连接程序将在编译完成是计算出 app_start 的实际地址(设若实际地址为 0x10000 ),这个实际地址是根据 ld 文件计算出来(因为连接器假定该程序将被加载到由 ld 文件指明的内存空间)。但实际上由于内存分配的关系,操作 系统在加载时无法保证程序将按 ld 文件加载。这时如果程序仍然跳转到绝对地址 0x10000 处执行,通常情况这是不正确的。一个解决办法是增加一个存储空 间,用于存储 app_start 的实际地址,设若使用变量 addr 表示这个存储空间。则以上这句程序将改为:
movl addr, a0;
jsr (a0);
增加的变量 addr 将在数据段中占用一个 4 字节的空间,连接器将 app_start 的绝对地址存储到该变量。在可执行文件加载时,可执行文件加载器根据程 序将要加载的内存空间计算出 app_start 在内存中的实际位置,写入 addr 变量。系统在实际处理是不需要知道这个变量的确切存储位置(也不可能知 道),系统只要对整个 reloc 段进行处理就可以了( reloc 段有标识,系统可以读出来)。处理很简单只需要对 reloc 段中存储的值统一加上一个偏置 (如果加载的空间比预想的要靠前,实际上是减去一个偏移量)。偏置由实际的物理地址起始值同 ld 文件指定的地址起始值相减计算出。
这种 reloc 的方式部分是由 uClinux 的内存分配问题引起的,这一点将在 uClinux 内存管理分析时说明。
针对实时性的解决方案
uClinux
本身并没有关注实时问题,它并不是为了 Linux 的实时性而提出的。另外有一种 Linux–Rt-linux 关注实时问题。 Rt- linux 执行管理器把普通 Linux 的内核当成一个任务运行,同时还管理了实时进程。而非实时进程则交给普通 Linux 内核处理。这种方法已经应用于很 多的操作系统用于增强操作系统的实时性,包括一些商用版 UNIX 系统, Windows NT 等等。这种方法优点之一是实现简单,且实时性能容易检验。优点之二是由于非实时进程运行于标准 Linux 系统,同其它 Linux 商用版本之间保持了很 大的兼容性。优点之三是可以支持硬实时时钟的应用。 uClinux 可以使用 Rt-linux 的 patch ,从而增强 uClinux 的实时性,使得 uClinux 可以应用于工业控制、进程控制等一些实时要求较高的应用。
uClinux 的内存管理
应该说 uClinux 同标准 Linux 的最大区别就在于内存管理,同时也由于 uClinux 的内存管理引发了一些标准 Linux 所不会出现的问题。本文将把 uClinux 内存管理同标准 Linux 的那内存管理部分进行比较分析。
标准 Linux 使用的虚拟存储器技术
标准 Linux 使用虚拟存储器技术,这种技术用于提供比计算机系统中实际使用的物理内存大得多的内存空间。使用者将感觉到好像程序可以使用非常大的内存空间,从而使得编程人员在写程序时不用考虑计算机中的物理内存的实际容量。
为了支持虚拟存储管理器的管理, Linux 系统采用分页( paging )的方式来载入进程。所谓分页既是把实际的存储器分割为相同大小的段,例如每个段 1024 个字节,这样 1024 个字节大小的段便称为一个页面( page )。
虚拟存储器由存储器管理机制及一个大容量的快速硬盘存储器支持。它的实现基于局部性原理,当一个程序在运行之前,没有必要全部装入内存,而是仅将那些当前 要运行的那些部分页面或段装入内存运行( copy-on-write ),其余暂时留在硬盘上程序运行时如果它所要访问的页(段)已存在,则程序继续运行, 如果发现不存在的页(段),操作系统将产生一个页错误( page fault ),这个错误导致操作系统把需要运行的部分加载到内存中。必要时操作系统还可以把不需要的内存页(段)交换到磁盘上。利用这样的方式管理存储 器,便可把一个进程所需要用到的存储器以化整为零的方式,视需求分批载入,而核心程序则凭借属于每个页面的页码来完成寻址各个存储器区段的工作。
标准 Linux 是针对有内存管理单元的处理器设计的。在这种处理器上,虚拟地址被送到内存管理单元( MMU ),把虚拟地址映射为物理地址。
通过赋予每个任务不同的虚拟
物理地址转换映射,支持不同任务之间的保护。地址转换函数在每一个任务中定义,在一个任务中的虚拟地址空间映射到物理内存 的一个部分,而另一个任务的虚拟地址空间映射到物理存储器中的另外区域。计算机的存储管理单元( MMU )一般有一组寄存器来标识当前运行的进程的转换表。 在当前进程将 CPU 放弃给另一个进程时(一次上下文切换),内核通过指向新进程地址转换表的指针加载这些寄存器。 MMU 寄存器是有特权的,只能在内核态才 能访问。这就保证了一个进程只能访问自己用户空间内的地址,而不会访问和修改其它进程的空间。当可执行文件被加载时,加载器根据缺省的 ld 文件,把程序加 载到虚拟内存的一个空间,因为这个原因实际上很多程序的虚拟地址空间是相同的,但是由于转换函数不同,所以实际所处的内存区域也不同。而对于多进程管理当 处理器进行进程切换并执行一个新任务时,一个重要部分就是为新任务切换任务转换表。我们可以看到 Linux 系统的内存管理至少实现了以下功能:
运行比内存还要大的程序。理想情况下应该可以运行任意大小的程序
◇ 可以运行只加载了部分的程序,缩短了程序启动的时间
◇ 可以使多个程序同时驻留在内存中提高 CPU 的利用率
◇ 可以运行重定位程序。即程序可以方于内存中的任何一处,而且可以在执行过程中移动。
◇ 写机器无关的代码。程序不必事先约定机器的配置情况。
◇ 减轻程序员分配和管理内存资源的负担。
◇ 可以进行共享
例如,如果两个进程运行同一个程序,它们应该可以共享程序代码的同一个副本。
◇ 提供内存保护,进程不能以非授权方式访问或修改页面,内核保护单个进程的数据和代码以防止其它进程修改它们。否则,用户程序可能会偶然(或恶意)的破坏内核或其它用户程序。
虚存系统并不是没有代价的。内存管理需要地址转换表和其他一些数据结构,留给程序的内存减少了。地址转换增加了每一条指令的执行时间,而对于有额外内存操 作的指令会更严重。当进程访问不在内存的页面时,系统发生失效。系统处理该失效,并将页面加载到内存中,这需要极耗时间的磁盘 I/O 操作。总之内存管理活 动占用了相当一部分 cpu 时间(在较忙的系统中大约占 10 %)。
uClinux 针对 NOMMU 的特殊处理
对于 uClinux 来说,其设计针对没有 MMU 的处理器,即 uClinux 不能使用处理器的虚拟内存管理技术(应该说这种不带有 MMU 的处理器在嵌入式设 备中相当普偏)。 uClinux 仍然采用存储器的分页管理,系统在启动时把实际存储器进行分页。在加载应用程序时程序分页加载。但是由于没有 MMU 管理, 所以实际上 uClinux 采用实存储器管理策略( real memeory management )。这一点影响了系统工作的很多方面。
uClinux 系统对于内存的访问是直接的,(它对地址的访问不需要经过 MMU ,而是直接送到地址线上输出),所有程序中访问的地址都是实际的物理地址。 操作系统对内存空间没有保护(这实际上是很多嵌入式系统的特点),各个进程实际上共享一个运行空间(没有独立的地址转换表)。
一个进程在执行前,系统必须为进程分配足够的连续地址空间,然后全部载入主存储器的连续空间中。与之相对应的是标准 Linux 系统在分配内存时没有必要保 证实际物理存储空间是连续的,而只要保证虚存地址空间连续就可以了。另外一个方面程序加载地址与预期( ld 文件中指出的)通常都不相同,这样 relocation 过程就是必须的。此外磁盘交换空间也是无法使用的,系统执行时如果缺少内存将无法通过磁盘交换来得到改善。
uClinux 对内存的管理减少同时就给开发人员提出了更高的要求。如果从易用性这一点来说, uClinux 的内存管理是一种倒退,退回了到了 UNIX 早 期或是 Dos 系统时代。开发人员不得不参与系统的内存管理。从编译内核开始,开发人员必须告诉系统这块开发板到底拥有多少的内存(假如你欺骗了系统,那将 在后面运行程序时受到惩罚),从而系统将在启动的初始化阶段对内存进行分页,并且标记已使用的和未使用的内存。系统将在运行应用时使用这些分页内存。
由于应用程序加载时必须分配连续的地址空间,而针对不同硬件平台的可一次成块(连续地址)分配内存大小限制是不同(目前针对 ez328 处理器的 uClinux 是 128k ,而针对 coldfire 处理器的系统内存则无此限制),所以开发人员在开发应用程序时必须考虑内存的分配情况并关注应用程序需 要运行空间的大小。另外由于采用实存储器管理策略,用户程序同内核以及其它用户程序在一个地址空间,程序开发时要保证不侵犯其它程序的地址空间,以使得程 序不至于破坏系统的正常工作,或导致其它程序的运行异常。
从内存的访问角度来看,开发人员的权利增大了(开发人员在编程时可以访问任意的地址空间),但与此同时系统的安全性也大为下降。此外,系统对多进程的管理将有很大的变化,这一点将在 uClinux 的多进程管理中说明。
虽然 uClinux 的内存管理与标准 Linux 系统相比功能相差很多,但应该说这是嵌入式设备的选择。在嵌入式设备中,由于成本等敏感因素的影响,普偏的 采用不带有 MMU 的处理器,这决定了系统没有足够的硬件支持实现虚拟存储管理技术。从嵌入式设备实现的功能来看,嵌入式设备通常在某一特定的环境下运行, 只要实现特定的功能,其功能相对简单,内存管理的要求完全可以由开发人员考虑。
标准 Linux 系统的进程、线程
进程:进程是一个运行程序并为其提供执行环境的实体,它包括一个地址空间和至少一个控制点,进程在这个地址空间上执行单一指令序列。进程地址空间包括可以访问或引用的内存单元的集合,进程控制点通过一个一般称为程序计数器( program counter,PC )的硬件寄存器控制和跟踪进程指令序列。
fork :由于进程为执行程序的环境,因此在执行程序前必须先建立这个能 " 跑 " 程序的环境。 Linux 系统提供系统调用拷贝现行进程的内容,以产生新的进 程,调用 fork 的进程称为父进程;而所产生的新进程则称为子进程。子进程会承袭父进程的一切特性,但是它有自己的数据段,也就是说,尽管子进程改变了所 属的变量,却不会影响到父进程的变量值。
父进程和子进程共享一个程序段,但是各自拥有自己的堆栈、数据段、用户空间以及进程控制块。换言之,两个进程执行的程序代码是一样的,但是各有各的程序计数器与自己的私人数据。
当内核收到 fork 请求时,它会先查核三件事:首先检查存储器是不是足够;其次是进程表是否仍有空缺;最后则是看看用户是否建立了太多的子进程。如果上述 说三个条件满足,那么操作系统会给子进程一个进程识别码,并且设定 cpu 时间,接着设定与父进程共享的段,同时将父进程的 inode 拷贝一份给子进程运 用,最终子进程会返回数值 0 以表示它是子进程,至于父进程,它可能等待子进程的执行结束,或与子进程各做个的。
exec 系统调用:该系统调用提供一个进程去执行另一个进程的能力, exec 系统调用是采用覆盖旧有进程存储器内容的方式,所以原来程序的堆栈、数据段与程序段都会被修改,只有用户区维持不变。
vfork 系统调用:由于在使用 fork 时,内核会将父进程拷贝一份给子进程,但是这样的做法相当浪费时间,因为大多数的情形都是程序在调用 fork 后就 立即调用 exec ,这样刚拷贝来的进程区域又立即被新的数据覆盖掉。因此 Linux 系统提供一个系统调用 vfork , vfork 假定系统在调用完成 vfork 后会马上执行 exec ,因此 vfork 不拷贝父进程的页面,只是初始化私有的数据结构与准备足够的分页表。这样实际在 vfork 调用完成后父子 进程事实上共享同一块存储器(在子进程调用 exec 或是 exit 之前),因此子进程可以更改父进程的数据及堆栈信息,因此 vfork 系统调用完成后,父进 程进入睡眠,直到子进程执行 exec 。当子进程执行 exec 时,由于 exec 要使用被执行程序的数据,代码覆盖子进程的存储区域,这样将产生写保护错误 ( do_wp_page )(这个时候子进程写的实际上是父进程的存储区域),
这个错误导致内核为子进程重新分配存储空间。当子进程正确开始执行后,将唤醒父进程,使得父进程继续往后执行。
uClinux 的多进程处理
uClinux 没有 mmu 管理存储器,在实现多个进程时( fork 调用生成子进程)需要实现数据保护。
uClinux 的 fork 和 vfork : uClinux 的 fork 等于 vfork 。实际上 uClinux 的多进程管理通过 vfork 来实现。这意味着 uClinux 系统 fork 调用完程后,要么子进程代替父进程执行(此时父进程已经 sleep )直到子进程调用 exit 退出,要么调用 exec 执行一个新 的进程,这个时候将产生可执行文件的加载,即使这个进程只是父进程的拷贝,这个过程也不能避免。当子进程执行 exit 或 exec 后,子进程使用 wakeup 把父进程唤醒,父进程继续往下执行。
uClinux 的这种多进程实现机制同它的内存管理紧密相关。 uClinux 针对 nommu 处理器开发,所以被迫使用一种 flat 方式的内存管理模式,启 动新的应用程序时系统必须为应用程序分配存储空间,并立即把应用程序加载到内存。缺少了 MMU 的内存重映射机制, uClinux 必须在可执行文件加载阶段 对可执行文件 reloc 处理,使得程序执行时能够直接使用物理内存。
5.Windows CE
Windows CE
是一个嵌入式操作系统。它是一个抢先式多任务并具有强大通信能力的 Win32 嵌入式操作系统,是微软专门为信息设备、移动应用、消费类电子产品、嵌入式应用等非 PC 领域而从头设计的战略性操作系统产品。 其中 CE 中的 C 代表袖珍( Compact )、消费( Consume )、通讯能力( Connectivity )和伴侣( Companion ); E 代表电子产品( Electronics )。
与 Windows 95/98 、 Windows NT 不同的是, Windows CE 是所有源代码全部由微软自行开发的嵌入式新型操作系统,其操作界面虽来源于 Windows 95/98 ,但 Windows CE 是基于 WIN32 API 重新开发、新型的信息设备的平台。 Windows CE 具有模块化、结构化和基于 Win32 应用程序接口和与处理器无关等特点。 Windows CE 不仅继承了传统的 Windows 图形界面,并且在 Windows CE 平台上可以使用 Windows 95/98 上的编程工具(如 Visual Basic 、 Visual C++ 等)、使用同样的函数、使用同样的界面风格,使绝大多数的应用软件只需简单的修改和移植就可以在 Windows CE 平台上继续使用。
不知你是否注意到,在我们的日常生活中,人们开始普遍使用手机、 PDA 、手持和掌上电脑等信息电器来储存和处理各种重要信息,这一切都似乎是在预示着一场新的革命。这场革命就是,计算机占领了桌面之后,继续其小型化和分散化的趋势,更广泛地进入人们工作、生活和娱乐的各个方面。这场革命又被近年来 Internet 的迅猛普及所推动,一个网上世界已经出现,人们随时、随地获取所需信息并保持与他人接触的需求愈发强烈。
早在微软创办之初,比尔 · 盖茨就曾梦想 “ 每人桌上一台 PC ,每台 PC 中运行微软的软件 ” ,这就是后来著名的 “ 信息随手可得 ” 的梦想,而这个梦想在今天 已经变成了现实。微软为 PC 提供了出色的操作系统平台 (Windows 9x / NT) 、高效率的软件开发工具和功能强大而易用的通用软件 (Microsoft Office 等 ) ,使许多人的工作和生活从计算机技术中受益无穷。
但是 PC 的价格、使用的复杂性仍使得许多人与之无缘。 PC 文化仍不是彻底的 “ 庶民文化 ” ,目前 PC 的复杂性对于更为普遍的大众来说仍是一种 “ 精英工具 ” 。 PC 已成为人们进入网上世界的最后一道门坎,例如中国已在 Internet 干线、接入、内容提供等诸方面投入巨资,但就因为这一 “ 最后一公里 ” 难题,中国的 Internet 产业迟迟不能起飞。
IBM
在 80 年代初犯下的错误:当年 IBM 固守 “ 主机文化 ” ,抱残守缺,错失了电脑向桌面这一新疆域拓展的良机,成为自己引发的 PC 革命的旁观者。所 以微软在向个人桌面和企业管理领域提供了两个方便易用且功能强大的操作系统之后,又从头设计了 Windows CE ,以面向更为广大的移动计算、信息家电等被微软称之为 “ 非 PC” 的应用领域。微软希望在这一新的应用领域仍然能够扮演操作系统平台、开发工具和通用软 件供应商的传统角色。
若把 CE 看作是电脑启蒙( Computer Evangelism ),就更能充分反映微软从头设计一个全新的操作系统的意义。
嵌入式操作系统是一种用途广泛的系统软件。工业控制是它的传统应用领域,在这一领域里已有一些存在了多年的比较成功的嵌入式操作系统。但近年来随着家 电信息化成为愈来愈明显的趋势,对嵌入式操作系统提出了许多新的要求,例如熟悉和友好的用户界面、统一的编程界面、强大的通讯功能等等都已变得日趋重要。
而恰好从一开始,微软就以其操作系统产品而闻名。从 MS DOS 到 Windows 9x / NT 、以及现在的 Windows CE ,微软公司最强大的软件产品往往是那些最终用户看不见的产品。 Windows 操作系统包含用户可见部分以及用于与计算机交互的用户界面部分,但还有许多更强大的功能是 “ 冰山隐藏在水面之下的部分 ” ,例如与其他计算机通讯的能力、 多媒体等等。 Windows CE 就是具备这些强大功能的、微软的操作系统家族中的最新成员。
Windows CE
的设计目标
Windows CE
的设计目标是:模块化及可伸缩性、实时性能好,通信能力强大,支持多种 CPU 。
从操作系统内核的角度看, Windows CE 具有灵活的电源管理功能,包括睡眠/唤醒模式。在 Windows CE 中,还使用了对象存储 (Object Store) 技术,包括文件系统、注册表及数据库。它还具有很多高性能、高效率的操作系统特性,包括按需换页、共享存储、交叉处理同步、支持大容量堆 (Heap) 等。
Windows CE
拥有良好的通信能力。它广泛支持各种通信硬件,亦支持直接的局域网连接以及拨号连接,并提供与 PC 、内部网以及 Internet 的连接,包括用于应用 级数据传输的设备至设备间的连接。在提供各种基本的通信基础结构的同时, Windows CE 还提供与 Windows 9x / NT 的最佳集成和通信。
Windows CE
的图形用户界面相当出色。它拥有基于 Microsoft Internet Explorer 的 Internet 浏览器,此外,还支持 TrueType 字体。开发人员可以利用丰富灵活的控件库在 Windows CE 环境下为嵌入式应用建立各种专门的图形用户界面。 Windows CE 甚至还能支持如手写体和声音识别、动态影像、 3D 图形等特殊应用。
Windows CE
常见误解纠正
误解一: Windows CE 等于手持电脑。
Windows CE
是模块化、结构化的操作系统,也是许多截然不同的设备的基础,而不仅支持手持电脑。
误解二: Windows CE 是 Windows 95 或 NT 的简化版。
Windows CE
是基于 Win32 API 而从头开发的,是新型的信息设备的平台。
误解三:掌上电脑是手持电脑的一种。
掌上电脑 (Palm PC) 的操作系统内核与手持电脑 (Handheld PC) 一样,但各自有其独特的用户界面和应用程序。
Windows CE
作业系统是 Windows 家族中的成员,专门设计给掌上型电脑 (HPCs) 所使用的电脑环境。这样的作业系统可使完整的可携式技术与现有的 Windows 桌面技术整合工作。 Windows Mobile 2003 for Smartphone 操作系统与 Windows Mobile 2003 for Pocket PC 操作系统一样,都是基于 Windows CE 架构的。
二. 嵌入式操作系统选择原则和对比
下面介绍了选择嵌入式操作系统应遵循的六条原则,并比较了目前几种嵌入式操作系统 VxWorks 、 WindowsCE 、嵌入式 Linux 、μ C/OS- Ⅱ等各自的优缺点。
嵌入式系统是以应用为中心,软硬件可裁减的,适用于对功能、可靠性、成本、体积、功耗等综合性严格要求的专用计算机系统。具有软件代码小、高度自动化、响应速度快等特点,特别适合于要求实时和多任务的体系。嵌入式系统主要由嵌入式处理器、相关支撑硬件、嵌入式操作系统及应用软件系统等组成,它是可独立工作的“器件”。
一、嵌入式操作系统的发展
作为嵌入式系统(包括硬、软件系统)极为重要的组成部分的嵌入式操作系统,通常包括与硬件相关的底层驱动软件、系统内核、设备驱动接口、通信协议、图形界面、标准化浏览器等。嵌入式操作系统具有通用操作系统的基本特点,如能够有效管理越来越复杂的系统资源;能够把硬件虚拟化,使得开发人员从繁忙的驱动程序移植和维护中解脱出来;能够提供库函数、驱动程序、工具集以及应用程序。与通用操作系统相比较,嵌入式操作系统在系统实时高效性、硬件的相关依赖性、软件固态化以及应用的专用性等方面具有较为突出的特点。
嵌入式操作系统伴随着嵌入式系统的发展经历了四个比较明显的阶段:
第一阶段:无操作系统的嵌入算法阶段,以单芯片为核心的可编程控制器形式的系统,具有与监测、伺服、指示设备相配合的功能。应用于一些专业性极强的工业控制系统中,通过汇编语言编程对系统进行直接控制,运行结束后清除内存。系统结构和功能都相对单一,处理效率较低,存储容量较小,几乎没有用户接口。
第二阶段:以嵌人式 CPU 为基础、简单操作系统为核心的嵌入式系统。 CPU 种类繁多,通用性比较差;系统开销小,效率高;一般配备系统仿真器,操作系统具有一定的兼容性和扩展性;应用软件较专业,用户界面不够友好;系统主要用来控制系统负载以及监控应用程序运行。
第三阶段:通用的嵌人式实时操作系统阶段,以嵌入式操作系统为核心的嵌入式系统。能运行于各种类型的微处理器上,兼容性好;内核精小、效率高,具有高度的模块化和扩展性;具备文件和目录管理、设备支持、多任务、网络支持、图形窗口以及用户界面等功能;具有大量的应用程序接口( APl );嵌入式应用软件丰富。
第四阶段:以基于 Internet 为标志的嵌入式系统。这是一个正在迅速发展的阶段。目前大多数嵌入式系统还孤立于 Internet 之外,但随着 Internet 的发展以及 Internet 技术与信息家电、工业控制技术等结合日益密切,嵌入式设备与 Intemet 的结合将代表着嵌入式技术的真正未来。
二、使用实时操作系统的必要性
嵌入式实时操作系统在目前的嵌入式应用中用得越来越广泛,尤其在功能复杂、系统庞大的应用中显得愈来愈重要。
1
.嵌人式实时操作系统提高了系统的可靠性。在控制系统中,出于安全方面的考虑,要求系统起码不能崩溃,而且还要有自愈能力。不仅要求在硬件设计方面提高系统的可靠性和抗干扰性,而且也应在软件设计方面提高系统的抗干扰性,尽可能地减少安全漏洞和不可靠的隐患。长期以来的前后台系统软件设计在遇到强干扰时,使得运行的程序产生异常、出错、跑飞,甚至死循环,造成了系统的崩溃。而实时操作系统管理的系统,这种干扰可能只是引起若干进程中的一个被破坏,可以通过系统运行的系统监控进程对其进行修复。通常情况下,这个系统监视进程用来监视各进程运行状况,遇到异常情况时采取一些利于系统稳定可靠的措施,如把有问题的任务清除掉。
2
.提高了开发效率,缩短了开发周期。在嵌入式实时操作系统环境下,开发一个复杂的应用程序,通常可以按照软件工程中的解耦原则将整个程序分解为多个任务模块。每个任务模块的调试、修改几乎不影响其他模块。商业软件一般都提供了良好的多任务调试环境。
3
.嵌入式实时操作系统充分发挥了 32 位 CPU 的多任务潜力。 32 位 CPU 比 8 、 16 位 CPU 快,另外它本来是为运行多用户、多任务操作系统而设计的,特别适于运行多任务实时系统。 32 位 CPU 采用利于提高系统可靠性和稳定性的设计,使其更容易做到不崩溃。例如, CPU 运行状态分为系统态和用户态。将系统堆栈和用户堆栈分开,以及实时地给出 CPU 的运行状态等,允许用户在系统设计中从硬件和软件两方面对实时内核的运行实施保护。如果还是采用以前的前后台方式,则无法发挥 32 位 CPU 的优势。从某种意义上说,没有操作系统的计算机(裸机)是没有用的。在嵌入式应用中,只有把 CPU 嵌入到系统中,同时又把操作系统嵌入进去,才是真正的计算机嵌入式应用。
三、嵌入式操作系统选型
当我们在设计信息电器、数字医疗设备等嵌入式产品时,嵌入式操作系统的选择至关重要。一般而言,在选择嵌入式操作系统时,可以遵循以下原则。总的来说,就是“做加法还是做减法”的问题。
(一)市场进入时间
制定产品时间表与选择操作系统有关系,实际产品和一般演示是不同的。目前是 Windows 程序员可能是人力资源最丰富的。现成资源最多的也就可能是 WinCE 。使用 WinCE 能够很快进入市场。因为 WinCE+X86 做产品实际上是在做减法,去掉你不要的功能,能很快出产品,但伴随的可能是成本高,核心竞争力差。而某些高效的操作系统可能由于编程人员缺乏,或由于这方面的技术积累不够,影响开发进度。
(二)可移植性
操作系统相关性。当进行嵌入式软件开发时,可移植性是要重点考虑的问题。良好的软件移植性应该比较好,可以在不同平台、不同系统上运行,跟操作系统无关。软件的通用性和软件的性能通常是矛盾的。即通用以损失某些特定情况下的优化性能为代价。很难设想开发一个嵌入式浏览器而仅能在某一特定环境下应用。反过来说,当产品与平台和操作系统紧密结合时,往往你的产品的特色就蕴含其中。
(三)可利用资源
产品开发不同于学术课题研究,它是以快速、低成本、高质量的推出适合用户需求的产品为目的的。集中精力研发出产品的特色,其他功能尽量由操作系统附加或采用第三方产品,因此操作系统的可利用资源对于选型是一个重要参考条件。 Linux 和 WinCE 都有大量的资源可以利用,这是他们被看好的重要原因。其他有些实时操作系统由于比较封闭,开发时可以利用的资源比较少,因此多数功能需要自己独立开发。从而影响开发进度。近来的市场需求显示,越来越多的嵌入式系统,均要求提供全功能的 Web 浏览器。而这要求有一个高性能、高可靠的 GUI 的支持。
(四)系统定制能力
信息产品不同于传统 PC 的 Wintel 结构的单纯性,用户的需求是千差万别的,硬件平台也都不一样,所以对系统的定制能力提出了要求。要分析产品是否对系统底层有改动的需求,这种改动是否伴随着产品特色 ?Linux 由于其源代码开放的天生魅力,在定制能力方面具有优势。随着 WinCE3.0 原码的开放,以及微软在嵌入式领域力度的加强,其定制能力会有所提升。
(五)成本
成本是所有产品不得不考虑的问题。操作系统的选择会对成本有什么影响呢 ?Linux 免费, WinCE 等商业系统需要支付许可证使用费,但这都不是问题的答案。成本是需要综合权衡以后进行考虑的——选择某一系统可能会对其他一系列的因素产生影响,如对硬件设备的选型、人员投入、以及公司管理和与其他合作伙伴的共同开发之间的沟通等许多方面的影响。
(六)中文内核支持
国内产品需要对中文的支持。由于操作系统多数是采用西文方式,是否支持双字节编码方式,是否遵循 GBK , GBl8030 等各种国家标准,是否支持中文输入与处理,是否提供第三方中文输入接口是针对国内用户的嵌入式产品的必需考虑的重要因素。
上面提到用 WinCE+x86 出产品是减法,这实际上就是所谓 PC 家电化;另外一种做法是加法,利用家电行业的硬件解决方案(绝大部分是非 x86 的)加以改进,加上嵌入式操作系统,再加上应用软件。这是所谓家电 PC 化的做法,这种加法的优势是成本低,特色突出,缺点是产品研发周期长,难度大(需要深入了解硬件和操作系统)。如果选择这种做法, Linux 是一个好选择,它让你能够深入到系统底层,如果你愿意并且有能力。
四、几种代表性嵌入式操作系统比较
(一) VxWorks
VxWorks
操作系统是美国 WindRiver 公司于 1983 年设计开发的一种嵌入式实时操作系统( RTOS ),是 Tornado 嵌入式开发环境的关键组成部分。良好的持续发展能力、高性能的内核以及友好的用户开发环境,在嵌人式实时操作系统领域逐渐占据一席之地。
VxWorks
具有可裁剪微内核结构;高效的任务管理;灵活的任务间通讯;微秒级的中断处理;支持 POSIX 1003 . 1b 实时扩展标准;支持多种物理介质及标准的、完整的 TCP/IP 网络协议等。
然而其价格昂贵。由于操作系统本身以及开发环境都是专有的,价格一般都比较高,通常需花费 10 万元人民币以上才能建起一个可用的开发环境,对每一个应用一般还要另外收取版税。一般不通供源代码,只提供二进制代码。由于它们都是专用操作系统,需要专门的技术人员掌握开发技术和维护,所以软件的开发和维护成本都非常高。支持的硬件数量有限。
(二) Windows CE
Windows CE
与 Windows 系列有较好的兼容性,无疑是 Windows CE 推广的一大优势。其中 WinCE3.0 是一种针对小容量、移动式、智能化、 32 位、了解设备的模块化实时嵌人式操作系统。为建立针对掌上设备、无线设备的动态应用程序和服务提供了一种功能丰富的操作系统平台,它能在多种处理器体系结构上运行,并且通常适用于那些对内存占用空间具有一定限制的设备。它是从整体上为有限资源的平台设计的多线程、完整优先权、多任务的操作系统。它的模块化设计允许它对从掌上电脑到专用的工业控制器的用户电子设备进行定制。操作系统的基本内核需要至少 200KB 的 ROM 。由于嵌入式产品的体积、成本等方面有较严格的要求,所以处理器部分占用空间应尽可能的小。系统的可用内存和外存数量也要受限制,而嵌入式操作系统就运行在有限的内存(一般在 ROM 或快闪存储器)中,因此就对操作系统的规模、效率等提出了较高的要求。从技术角度上讲, Windows CE 作为嵌入式操作系统有很多的缺陷:没有开放源代码,使应用开发人员很难实现产品的定制;在效率、功耗方面的表现并不出色,而且和 Windows 一样占用过的系统内存,运用程序庞大;版权许可费也是厂商不得不考虑的因素。
(三)嵌入式 Linux
这是嵌入式操作系统的一个新成员,其最大的特点是源代码公开并且遵循 GPL 协议,在近一年多以来成为研究热点,据 IDG 预测嵌入式 Linux 将占未来两年的嵌入式操作系统份额的 50% 。
由于其源代码公开,人们可以任意修改,以满足自己的应用,并且查错也很容易。遵从 GPL ,无须为每例应用交纳许可证费。有大量的应用软件可用。其中大部分都遵从 GPL ,是开放源代码和免费的。可以稍加修改后应用于用户自己的系统。有大量的免费的优秀的开发工具,且都遵从 GPL ,是开放源代码的。有庞大的开发人员群体。无需专门的人才,只要懂 Unix/Linux 和 C 语言即可。随着 Linux 在中国的普及,这类人才越来越多。所以软件的开发和维护成本很低。优秀的网络功能,这在 Internet 时代尤其重要。稳定——这是 Linux 本身具备的一个很大优点。内核精悍,运行所需资源少,十分适合嵌入式应用。
支持的硬件数量庞大。嵌入式 Linux 和普通 Linux 并无本质区别, PC 上用到的硬件嵌入式 Linux 几乎都支持。而且各种硬件的驱动程序源代码都可以得到,为用户编写自己专有硬件的驱动程序带来很大方便。
在嵌入式系统上运行 Linux 的一个缺点是 Linux 体系提供实时性能需要添加实时软件模块。而这些模块运行的内核空间正是操作系统实现调度策略、硬件中断异常和执行程序的部分。由于这些实时软件模块是在内核空间运行的,因此代码错误可能会破坏操作系统从而影响整个系统的可靠性,这对于实时应用将是一个非常严重的弱点。
(四)μ C/OS 一Ⅱ
μ C/OS 一Ⅱ是著名的源代码公开的实时内核,是专为嵌入式应用设计的,可用于 8 位, 16 位和 32 位单片机或数字信号处理器( DSP )。它是在原版本 μ C/OS 的基础上做了重大改进与升级,并有了近十年的使用实践,有许多成功应用该实时内核的实例。它的主要特点如下:
公开源代码,容易就能把操作系统移植到各个不同的硬件平台上;
可移植性,绝大部分源代码是用 C 语言写的,便于移植到其他微处理器上;
可固化;
可裁剪性,有选择的使用需要的系统服务,以减少斗所需的存储空间;
占先式,完全是占先式的实时内核,即总是运行就绪条件下优先级最高的任务;
多任务,可管理 64 个任务,任务的优先级必须是不同的,不支持时间片轮转调度法;
可确定性,函数调用与服务的执行时间具有其可确定性,不依赖于任务的多少;
实用性和可靠性,成功应用该实时内核的实例,是其实用性和可靠性的最好证据。
由于μ C/OS 一Ⅱ仅是一个实时内核,这就意味着它不像其他实时存在系统那样提供给用户的只是一些 API 函数接口,还有很多工作需要用户自己去完成。
五、结束语
在嵌入式应用中,使用实时操作系统( RTOS )是当前嵌入式应用的一个特点,一种趋势,也是单片机应用从低水平向高水平的一个进步。在实际的应用中,根据不同的要求和条件选择合适的操作系统,使开发工作更容易,设计出更完美的嵌入式系统。