admin 发表于 2008-11-12 18:02:00

嵌入式linux系统开发概述

原文地址:
http://blog.csdn.net/gufeng77/archive/2007/03/05/1520990.aspx
http://blog.csdn.net/images/authorship.gif 嵌入式linux系统开发概述收藏新一篇: Xscale(PXA255)存储器接口 | 旧一篇: Step by Step构建嵌入式Linux系统平台嵌入式linux系统开发概述
作者:谷丰,gufeng77@126.com" target="_blank">您可以通过gufeng77@126.com和他联系
基于linux的嵌入式系统开发是一个很大的课题,涵盖了从硬件到软件设计的多个领域,由于linux的开源特性,导致开发中可以使用的软件和工具多不胜数,从最底层与系统硬件直接打交道的引导装载程序(bootloader),到linux操作系统的分发版(distribution),再到上层的图形用户界面(GUI)乃至应用程序(application),可供选择的软件实在是太多了,这对开发者来说是一种恩赐。但由于标准的不统一,对于刚刚步入这个领域的初学者来说,很难在短时间内全部了解和掌握它们。本文论述了嵌入式linux开发的基本模式和概念,给出了一些常用的软件和工具,旨在带领他们更快的走入这个奇妙的世界。

1   引导装载程序(bootloader)
引导装载程序通常是在任何硬件上执行的第一段代码,它的主要任务视装载设备的不同而不同。在台式机和笔记本这样的常规系统中,经常存在多个操作系统并存的情况,因此bootloader的主要作用就是选择系统使用何种操作系统来引导。常用的引导程序有LILO或GRUB,通常将它们装入硬盘的主引导记录(Master Boot Record)中,或者装入linux 驻留的磁盘的第一个扇区。

在嵌入式系统中,情况有些不同。首先,嵌入式设备通常需要经常地移
动,考虑到在移动过程中的震动,一般不会采用机械式结构设计的硬盘为存
储设备;而且从成本控制上说,硬盘的价格比较高,除非是需要大容量存储
的场合,硬盘不适合作为嵌入式设备的存储介质。目前采用得比较多的是闪
存设备,闪存设备是与存储设备功能类似的特殊芯片,而且它们能持久存储
信息----即在重新引导时不会擦除其内容,Flash、Disk on Chip和Compact
Flash卡就是使用得比较多的这类设备。另外,由于一般嵌入式设备上只会有
一个操作系统,所以bootloader的主要功能有所变化,不再是用来选择操作
系统,而是为了更快地在存储介质上下载linux内核和文件系统(filesystem
包含了图形用户界面等应用程序,将在后面介绍)。这是因为我们一般通过芯
片的JTAG口来实现引导程序的装载,JTAG口的速度比较慢,对于只有十几K大
小的bootloader来说,装载的时间不会很长,可是针对一个功能完善的嵌入
式设备,比如PDA,它的软件系统包括了linux内核和以上的各种应用,加在
一起最少都会有十几兆,如果都通过JTAG来下载的话,恐怕几个小时都是不
够用的。而且通常内核和应用需要多次的修改和调试才得到最终的成熟的版
本,如此频繁的下载要都通过JTAG来实现,显然是不现实的。因此,为了解
决这个问题,通常的做法是在bootloader中实现网卡或USB的驱动,通过网络
或USB接口来实现软件的下载功能。
目前流行的并可免费使用的linux引导装载程序有Blob、U-boot、Redboot和Bootldr,它们可以广泛地应用在X86、ARM、PPC和MIPS等平台上,对于基于ARM核设计的PXA255芯片,当然也是适合的。
前面提到bootloader可以通过芯片的JTAG口下载到闪存上的,PXA255采用的就是这种方式。这种方式需要专用软件。专用软件可以直接与目标机(在嵌入式开发中,嵌入式设备通常被称为目标机)上的闪存设备进行交互并将引导装载程序安装在闪存的给定位置中。这个软件使用目标系统上的 JTAG 端口,JTAG是用于执行外部输入(通常来自主机,及用作开发的PC机系统)的指令的接口。JFlash-linux 就是一种用于直接写闪存的流行工具。它支持为数众多的闪存芯片;它在主机上执行并通过使用主机的并行端口与目标系统的JTAG接口访问目标的闪存芯片。当然,这意味着需要有专门的用来连接目标机JTAG口和主机并行接口的通讯线。主机和目标机的连接方式见图1.1所示。
http://p.blog.csdn.net/images/p_blog_csdn_net/gufeng77/8ebe553e242b437cae88e9df5a893381.png
图1.1目标机JTAG和主机并行端口的连接
Jflash-linux在linux和windows版本中都可使用,可以在命令行中用以下命令启动它:
#Jflash-linux <bootloader>
还有某些种类的嵌入式芯片具有微小的引导代码----根据几个字节的指令----它将初始化一些 DRAM设置并启用目标机上的一个串行(或者 USB,或者以太网)端口与主机程序通信。然后,主机程序或装入程序可以使用这个连接将引导装载程序传送到目标机上,并将它写入闪存。
在引导程序已装载并给予其控制后,这个引导装载程序执行下列各类功能:
初始化CPU速度
初始化内存,包括启用内存库、初始化内存配置寄存器等
初始化串行端口(如果在目标上有的话)
启用指令/数据高速缓存
设置堆栈指针
设置参数区域并构造参数结构和标记(这是重要的一步,因为内核在标
识根设备、页面大小、内存大小以及更多内容时要使用引导参数)
执行 POST(加电自检)来标识存在的设备并报告任何问题
为电源管理提供挂起/恢复支持
跳转到内核的开始

可以看出,bootloader初始化了一个芯片的最小系统,这是它另一个主要功能----检查基本硬件系统的设计是否正确。

2Linux内核
    Linux的源代码组织非常复杂,幸好我们不用将它们完全弄懂,现在我们需要的是知道各个部分的大致功能,然后再在以后开发过程中,针对不同的系统需求,修改内核中特定的某个部分就可以了。下面首先来看看是linux源码文件的组织结构:
kernel/               linux内核(非常小)
lib/                  各种内核需要使用的库文件
MAINTAINERS         内核各部分的维护者
mm/                   内存管理单元
net/                  网络系统
README                readme文件
REPORTING_BUGS      报告bug的指导
scripts/            一些脚本
security/             安全模式的实现

sound/                声卡支持和驱动
usr/                  工具
arch/               硬件相关代码
COPYING               linux拷贝条件(GNU GPL)
CREDITS               linux的主要贡献者
crypto/               密码库
Documentation/      内核文档
drivers/            驱动程序
fs/                   文件系统
include/            内核头文件
include/asm-<arch>   硬件相关的头文件
include/linux         内核核心的头文件
init                  linux初始化代码
ipc/                  进程间通讯
Linux 社区正积极地为新硬件添加功能部件和支持、在内核中修正错误并且及时地进行常规改进,这也是导致目前内核源代码越来越庞大的原因。大约每 6 个月(或 6 个月不到)就有一个稳定的 linux 树的新发行版。不同的维护者维护针对特定体系结构的不同内核树和补丁。当为一个项目选择了一个内核时,您需要评估最新发行版的稳定性如何、它是否符合项目要求和硬件平台、从编程角度来看它的舒适程度以及其它难以确定的方面。还有一点也非常重要:找到需要应用于基本内核的所有补丁,以便为特定的体系结构调整内核。
内核布局分为特定于体系结构的部分和与体系结构无关的部分。内核中特定于体系结构的部分首先执行,设置硬件寄存器、配置内存映射、执行特定于体系结构的初始化,然后将控制转给内核中与体系结构无关的部分。系统的其余部分在这第二个阶段期间进行初始化。内核树下的目录 arch/ 由不同的子目录组成,每个子目录用于一个不同的体系结构(MIPS、ARM、i386、SPARC、PPC 等)。每一个这样的子目录都包含 kernel/ 和 mm/ 子目录,它们包含特定于体系结构的代码来完成象初始化内存、设置 IRQ、启用高速缓存、设置内核页面表等操作。一旦装入内核并给予其控制,就首先调用这些函数,然后初始化系统的其余部分。
根据可用的系统资源和引导装载程序的功能,内核可以编译成vmlinux、Image 或zImage。vmlinux和zImage之间的主要区别在于vmlinux是实际的(未压缩的)可执行文件,而zImage是或多或少包含相同信息的自解压压缩文件—--只是压缩它以处理(通常是 Intel 强制的)640 KB 引导时间的限制。有关所有这些的权威性解释,请参阅 Linux Magazine 的文章“Kernel Configuration: dealing with the unexpected”。

3
工具链(Toolchain)
设置工具链在主机机器上创建一个用于编译将在目标上运行的内核和应
用程序的构建环境—--这是因为目标硬件可能没有与主机兼容的二进制执行级别。
工具链由一套用于编译、汇编和链接内核及应用程序的组件组成。 这些组件包括:
Binutils — 用于操作二进制文件的实用程序集合。它们包括诸如 ar、as、objdump、objcopy这样的实用程序;
Gcc — GNU C编译器;
Glibc — 所有用户应用程序都将链接到的C库。避免使用任何C库函数的内核和其它应用程序可以在没有该库的情况下进行编译。

构建工具链建立了一个交叉编译器环境。本地编译器编译与本机同类的处理器的指令。交叉编译器运行在某一种处理器上,却可以编译另一种处理器的指令。从头设置交叉编译器工具链可不是一项简单的任务:它包括下载源代码、修补补丁、配置、编译、设置头文件、安装以及很多很多的操作。另外,这样一个彻底的构建过程对内存和硬盘的需求是巨大的。如果没有足够的内存和硬盘空间,那么在构建阶段由于相关性、配置或头文件设置等问题会突然冒出许多问题。

因此能够从因特网上获得已预编译的二进制文件是一件好事(但不太好的一点是,目前它们大多数只限于基于ARM的系统,但迟早会改变的)。一些比较流行的已预编译的工具链包括那些来自Compaq(Familiar Linux )、LART(LART Linux和Embedian(基于Debian但与它无关)的工具链 — 所有这些工具链都用于基于ARM的平台。Intel的PXA255芯片就是基于ARM设计的。
4   设备驱动程序
嵌入式系统通常有许多设备用于与用户交互,象触摸屏、小键盘、滚动
轮、传感器、RS232接口、LCD等等。除了这些设备外,还有许多其它专用设
备,包括闪存、USB、GSM等。内核通过所有这些设备各自的设备驱动程序来
控制它们,包括GUI用户应用程序也通过访问这些驱动程序来访问设备。

开发者编写驱动程序是应该特别注意下面所提到的概念:编写访问硬
件的内核代码是不要给用户强加任何策略。因为不同的用户有不同的需求,
驱动程序应该处理如何使硬件可用的问题,而将怎样使用硬件的问题留给上
层应用。因此,当驱动程序只提供了访问硬件的功能而没有附加任何限制时
,这个驱动程序就比较灵活。然而,有时候我们也需要在驱动程序中实现一
些策略。例如,某个数字I/O驱动程序只提供了以字节为单位访问硬件的方法
,这样就省去了编写额外代码以处理单个数据位的麻烦。

如果从另一个角度来看驱动程序,那么它可以被看作是应用和实际设备
之间的一个软件层。这种定位使开发者可以选择如何展现设备特性:即使对于相同的设备,不同的驱动程序也可以提供不同的功能。实际的驱动程序设计应该在许多考虑因素之间取得平衡。例如,某个驱动程序可能同时被多个进程使用,我们就应该考虑如何处理并发的问题:可以在设备上实现独立于硬件功能的内存映射;也可以提供一个函数库,以帮助应用程序开发者在已有原语的基础上实现新的策略。总之,驱动程序的设计主要还是综合考虑下面三方面的因素:提供给用户尽量多的选项、编写驱动程序占用较少的时间以及尽量保持程序简单而不至于错误丛生。
本节着重讨论通常几乎在每个嵌入式环境中都会使用的一些重要设备的
设备驱动程序。

4.1 帧缓冲区驱动程序(FrameBuffer)
这是最重要的驱动程序之一,因为通过这个驱动程序才能使系统屏幕显
示内容。帧缓冲区驱动程序通常有三层。最底层是基本控制台驱动程序
drivers/char/console.c,它提供了文本控制台常规接口的一部分。通过使
用控制台驱动程序函数,我们能将文本打印到屏幕上 — 但图形或动画还不
能(这样做需要使用视频模式功能,通常出现在中间层,也就是drivers-
/video/fbcon.c 中)。这个第二层驱动程序提供了视频模式中绘图的常规接
口。
帧缓冲区是显卡上的内存,需要将它内存映射到用户空间以便可以将图
形和文本能写到这个内存段上:然后这个信息将反映到屏幕上。帧缓冲区支持提高了绘图的速度和整体性能。这也是顶层驱动程序引人注意之处:顶层是非常特定于硬件的驱动程序,它需要支持显卡不同的硬件方面 — 象启用/禁用显卡控制器、深度和模式的支持以及调色板等。所有这三层都相互依赖以实现正确的视频功能。与帧缓冲区相对应的设备是/dev/fb0(主设备号29,次设备号0)。可以用下面的命令来创建该设备:
#mknod /dev/fb0 c 29 0
有一个简单的比喻来理解帧缓冲驱动。假设当前需要的显示分辨率是640x480x16bpp(16bpp代表16位色,一般的RGB排列为565,),那么要存储整个屏幕的像素信息所需要的内存大小为640x480x16/8 = 600K bytes(一个像素的16位色需要两个字节来表示)。帧缓冲驱动即在内存中分配了上述大小的一块区域,同时与实际屏幕上的像素一一对应。
如果我们要改变屏幕上某个像素的颜色显示,首先计算该颜色的16位的RGB排列,然后计算出该像素在内存中的偏移量,最后操作fb0设备,重画该像素。下面的代码将屏幕上的第二排的第二个像素设置成白色:
{
int fd, pixel_addr, pixel_color, ;

pixel_addr = (640+1)x16/8;      /* 得到像素偏移地址 */
pixel_color = 0xffff;         /* 设置像素点颜色 */

fd = open(“/dev/fb0”, O_RDWR); /* 打开framebuffer设备 */
if (fd >= 0)
{
    lseek(fd, pixel_addr, SEEK_SET);    /* 找到该像素 */
    write(fd, pixel_color, 2);          /* 重画该像素 */
}
现在一般的linux内核已经包含了对帧缓冲驱动的支持,我们要作的只是在内核配置选项中加入它:
#make menuconfig(命令行下),或xconfig(XWindow下)。
与 frame buffer device有关的选项有(用空格键来进行选中或去除,其余编译选项请参考其它资料):
Code maturity level opetions
   Prompt for development and/or incomplete codes/drivers
   Console drivers
   Video mode selection support
   ...
   Support for frame buffer devices
   ...
   VESA VGA graphics console
   ...
   Advance low level driver options
   ...


Do you wish to save your new kernel configuration?

编译安装内核:
#make dep
#make bzImage

4.2 输入设备驱动程序

可触摸板是用于嵌入式设备的最基本的用户交互设备之一 — 小键盘、传感器和滚动轮也包含在许多不同设备中以用于不同的用途。

触摸板设备的主要功能是随时报告用户的触摸,并标识触摸的坐标。这通常在每次发生触摸时,通过生成一个中断来实现。然后,这个设备驱动程序的角色是每当出现中断时就查询触摸屏控制器,并请求控制器发送触摸的坐标。一旦驱动程序接收到坐标,它就将有关触摸和任何可用数据的信号发送给用户应用程序,并将数据发送给应用程序(如果可能的话)。然后用户应用程序根据它的需要处理数据。

几乎所有输入设备 — 包括小键盘 — 都以类似原理工作。

输入设备驱动程序通常需要与上层的GUI应用接口。比如触摸板需要和GUI的鼠标显示结合起来,随着用户触摸位置的不同,屏幕上鼠标的图标移动到相应的位置。一般在GUI中有专门处理外部输入的文件,修改这些文件,可以支持自己的输入设备。


4.3 闪存MTD驱动程序
MTD设备是象闪存芯片、小型闪存卡、记忆棒等之类的设备,它们在嵌入
式设备中的使用正在不断增长。
MTD驱动程序是在linux下专门为嵌入式环境开发的新的一类驱动程序。
相对于常规块设备驱动程序,使用MTD驱动程序的主要优点在于MTD驱动程序
是专门为基于闪存的设备所设计的,所以它们通常有更好的支持、更好的管
理和基于扇区的擦除和读写操作的更好的接口。

5

嵌入式设备的文件系统
系统需要一种以结构化格式存储和检索信息的方法,这就需要文件系统的参与。文件系统指文件存在的物理空间,linux系统中每个分区都是一个文件系统,都有自己的目录层次结构。Linux会将这些分属不同分区的、单独的文件系统按一定的方式形成一个系统的总的目录层次结构。一个操作系统的运行离不开对文件的操作,因此必然要拥有并维护自己的文件系统。
用户可以根据可靠性、健壮性和/或增强的功能的需求来选择文件系统的类型。下一节将讨论几个可用选项及其优缺点。
5.1 第二版扩展文件系统(Ext2fs)

Ext2fs是linux事实上的标准文件系统,它已经取代了它的前任 — 扩展文件系统(或Extfs)。Extfs支持的文件大小最大为2GB,支持的最大文件名称大小为255个字符 — 而且它不支持索引节点(包括数据修改时间标记)。Ext2fs做得更好;它的优点是:
Ext2fs支持达4TB 的内存。
Ext2fs文件名称最长可以到1012个字符。
当创建文件系统时,管理员可以选择逻辑块的大小(通常大小可选择 1024、2048和4096字节)。
Ext2fs实现快速符号链接:不需要为此目的而分配数据块,并且将目标名称直接存储在索引节点(inode)表中。这使性能有所提高,特别是在速度上。

因为Ext2文件系统的稳定性、可靠性和健壮性,所以几乎在所有基于 linux的系统(包括台式机、服务器和工作站 — 并且甚至一些嵌入式设备)上都使用Ext2文件系统。然而,当在嵌入式设备中使用Ext2fs时,它有一些缺点:
Ext2fs是为象IDE设备那样的块设备设计的,这些设备的逻辑块大小是512字节,1K字节等这样的倍数。这不太适合于扇区大小因设备不同而不同的闪存设备;
Ext2文件系统并没有提供对基于扇区的擦除/写操作的良好管理。在Ext2fs中,为了在一个扇区中擦除单个字节,必须将整个扇区复制到RAM,然后擦除,然后重写入。考虑到闪存设备具有有限的擦除寿命(大约能进行100,000次擦除),在此之后就不能使用它们,所以这不是一个特别好的方法;
在出现电源故障时,Ext2fs不是防崩溃的;
Ext2文件系统不支持损耗平衡,因此缩短了扇区/闪存的寿命(损耗平衡确保将地址范围的不同区域轮流用于写和/或擦除操作以延长闪存设备的寿命);
Ext2fs没有特别完美的扇区管理,这使设计块驱动程序十分困难。
由于这些原因,通常相对于Ext2fs,在嵌入式环境中使用MTD/JFFS2组合是更好的选择。

5.2 用 Ramdisk 挂装 Ext2fs
Ramdisk是通过将计算机的RAM用作设备来创建和挂装文件系统的一种机制,它通常用于无盘系统(当然包括微型嵌入式设备,它只包含作为永久存储媒质的闪存芯片)。

通过使用Ramdisk的概念,可以在嵌入式设备中创建并挂装Ext2文件系统(以及用于这一目的的任何文件系统)。

下面的操作创建一个简单的基于Ext2fs的Ramdisk :
#mke2fs -vm0 /dev/ram 4096
#mount -t ext2 /dev/ram /mnt
#cd /mnt
#cp /bin, /sbin, /etc, /dev ... files in mnt
#cd ../
#umount /mnt
#dd if=/dev/ram bs=1k count=4096 of=ext2ramdisk
mke2fs是用于在任何设备上创建ext2文件系统的实用程序 — 它创建超级块、索引节点以及索引节点表等等。

在上面的用法中,/dev/ram 是上面构建有4096个块的ext2文件系统的设备。然后,将这个设备(/dev/ram)挂装在名为/mnt的临时目录上并且复制所有必需的文件。一旦复制完这些文件,就卸装这个文件系统并且设备(/dev/ram)的内容被转储到一个文件(ext2ramdisk)中,它就是所需的 Ramdisk(Ext2文件系统)。

上面的顺序创建了一个4MB的Ramdisk,并用必需的文件实用程序来填充它。

一些要包含在 Ramdisk 中的重要目录是:
/bin — 保存大多数象init、busybox、shell、文件管理实用程序等二进制文件。
/dev — 包含用在设备中的所有设备节点
/etc — 包含系统的所有配置文件
/lib — 包含所有必需的库,如libc、libdl 等

5.3 日志闪存文件系统,版本 2(JFFS2)

瑞典的Axis Communications开发了最初的JFFS,Red Hat的David Woodhouse对它进行了改进。 第二个版本,JFFS2,作为用于微型嵌入式设备的原始闪存芯片的实际文件系统而出现。JFFS2文件系统是日志结构化的,这意味着它基本上是一长列节点。每个节点包含有关文件的部分信息 — 可能是文件的名称、也许是一些数据。相对于 Ext2fs,JFFS2 因为有以下这些优点而在无盘嵌入式设备中越来越受欢迎:
JFFS2在扇区级别上执行闪存擦除/写/读操作要比Ext2文件系统好;
JFFS2提供了比Ext2fs更好的崩溃/掉电安全保护。当需要更改少量数据时,Ext2文件系统将整个扇区复制到内存(DRAM)中,在内存中合并新数据,并写回整个扇区。这意味着为了更改单个字,必须对整个扇区(64KB)执行读/擦除/写例程 — 这样做的效率非常低。要是运气差,当正在DRAM中合并数据时,发生了电源故障或其它事故,那么将丢失整个数据集合,因为在将数据读入DRAM后就擦除了闪存扇区。JFFS2附加文件而不是重写整个扇区,并且具有崩溃/掉电安全保护这一功能。
这可能是最重要的一点:JFFS2是专门为象闪存芯片那样的嵌入式设备创建的,所以它的整个设计提供了更好的闪存管理。

因为本文主要是写关于闪存设备的使用,所以在嵌入式环境中使用 JFFS2的缺点很少:
当文件系统已满或接近满时,JFFS2会大大放慢运行速度。这是因为垃圾收集的问题。

在linux下,用mkfs.jffs2命令创建JFFS2文件系统(基本上是使用JFFS2的Ramdisk)。

下面的操作创建 JFFS2 文件系统:
#mkdir jffsfile
#cd jffsfile

/* copy all the /bin, /etc, /usr/bin, /sbin/ binaries and /dev entries
that are needed for the filesystem here */

/* Type the following command under jffsfile directory to create the JFFS2 Image */

#./mkfs.jffs2 -e 0x40000 -p -o ../jffs.image
上面显示了 mkfs.jffs2 的典型用法。-e选项确定闪存的擦除扇区大小(通常是64千字节)。-p选项用来在映像的剩余空间用零填充。-o选项用于输出文件,通常是JFFS2文件系统映像 — 在本例中是jffs.image。一旦创建了 JFFS2文件系统,它就被装入闪存中适当的位置(引导装载程序告知内核查找文件系统的地址)以便内核能挂装它。


5.4 tmpfs
当linux运行于嵌入式设备上时,该设备就成为功能齐全的单元,许多守
护进程会在后台运行并生成许多日志消息。另外,所有内核日志记录机制,
象 syslogd、dmesg和klogd,会在/var和/tmp目录下生成许多消息。由于这
些进程产生了大量数据,所以允许将所有这些写操作都发生在闪存是不可取
的。由于在重新引导时这些消息不需要持久存储,所以这个问题的解决方案
是使用tmpfs。
tmpfs是基于内存的文件系统,它主要用于减少对系统的不必要的闪存
写操作这一唯一目的。因为tmpfs驻留在RAM中,所以写/读/擦除的操作发
生在RAM中而不是在闪存中。因此,日志消息写入RAM而不是闪存中,在重新
引导时不会保留它们。tmpfs还使用磁盘交换空间来存储,并且当为存储文件
而请求页面时,使用虚拟内存(VM)子系统。
tmpfs的优点包括:
动态文件系统大小 — 文件系统大小可以根据被复制、创建或删除的文件或
目录的数量来缩放。使得能够最理想地使用内存;
速度 — 因为tmpfs驻留在RAM,所以读和写几乎都是瞬时的。即使以交换的
形式存储文件,I/O操作的速度仍非常快。
tmpfs的一个缺点是当系统重新引导时会丢失所有数据。因此,重要的数
据不能存储在tmpfs上。
诸如Ext2fs和JFFS2等大多数其它文件系统都驻留在底层块设备之上,而
tmpfs与它们不同,它直接位于VM上。因而,挂装tmpfs文件系统是很简单的
事:
/* Entries in /etc/rc.d/rc.sysinit for creating/using tmpfs */
# mount -t tmpfs tmpfs /var -o size=512k
# mkdir -p /var/tmp
# mkdir -p /var/log
# ln -s /var/tmp /tmp
上面的命令将在/var上创建tmpfs并将tmpfs的最大大小限制为512K。同时,tmp/和log/目录成为tmpfs的一部分以便在RAM中存储日志消息。

如果您想将tmpfs的一个项添加到/etc/fstab,那么它看起来象这样:
tmpfs /var tmpfs size=32m 0 0
这将在/var上挂装一个新的tmpfs文件系统。

6

图形用户界面(GUI)
从用户的观点来看,图形用户界面(GUI)是系统的一个最至关重要的方面:用户通过GUI与系统进行交互。所以GUI应该易于使用并且非常可靠。但它还需要是有内存意识的,以便在内存受限的、微型嵌入式设备上可以无缝执行。所以,它应该是轻量级的,并且能够快速装入。

另一个要考虑的重要方面涉及许可证问题。一些GUI分发版具有允许免费使用的许可证,甚至在一些商业产品中也是如此。另一些许可证要求如果想将GUI合并入项目中则要支付版税。
尽管嵌入式系统对GUI的需求越来越明显,但目前 GUI 的实现方法各有不同:
1.某些大型厂商有能力自己开发满足自身需要的GUI系统;
2.某些厂商没有将GUI作为一个软件层从应用程序中剥离,GUI的支持逻辑由应用程序自己负责;
3.采用某些比较成熟的GUI系统,比如XFree86或者其他。
在上述手段中,第2种方法是一种临时解决方案。利用这种手段编写的程序,无法将显示逻辑和数据处理逻辑划分开来,从而导致程序结构不好,不便于调试,并导致大量的代码重复。GUI是一种类似于操作系统的基础软件,这种软件系统应该遵循一定的标准,并且应该是开放源码的自由软件,从而可以让开放商集中精力开发自己的应用程序。目前看来,在linux之上进行(实时)嵌入式系统开发的厂商,一般选择如下几种GUI系统:紧缩的XFree86系统(Tiny-X)、MiniGUI、MicroWindows(Nano-X)、OpenGUI、QT/Embedded 等,下面将对这些系统进行简单介绍。

6.1 紧缩的XFree86系统(Tiny-X)

XFree86 Project, Inc.是一家生产XFree86的公司,该产品是一个可以免费重复分发、开放源码的X Windows系统。X Windows系统(X11)为应用程序以图形方式进行显示提供了资源,并且它是UNIX和类UNIX的机器上最常用的窗口系统。它很小但很有效,它运行在为数众多的硬件上,它对网络透明并且有良好的文档说明。X11为窗口管理、事件处理、同步和客户机间通信提供强大的功能 — 并且大多数开发人员已经熟悉了它的API。它具有对内核帧缓冲区的内置支持,并占用非常少的资源 — 这非常有助于内存相对较少的设备。X服务器支持VGA和非VGA图形卡,它对颜色深度1、2、4、8、16和32提供支持,并对渲染提供内置支持。
它的优点包括:
帧缓冲区体系结构的使用提高了性能;
占用的资源相对很小 — 大小在600K到700K字节的范围内,这使它很容易在小型设备上运行;
非常好的支持:在线有许多文档可用,还有许多专用于XFree86开发的邮递列表;
X API非常适合扩展。
它的缺点包括:
比最近出现的嵌入式 GUI 工具性能差。
此外,当与 GUI 中最新的开发 — 象专门为嵌入式环境设计的 Nano-X 或 QT/Embedded — 相比时,XFree86似乎需要更多的内存。

6.2 Microwindows(Nano-X)
Microwindows 是 Century Software的开放源代码项目,设计用于带小
型显示单元的微型设备。它有许多针对现代图形视窗环境的功能部件。象X一
样,有多种平台支持Microwindows。
Microwindows 体系结构是基于客户机/服务器的并且具有分层设计。最
底层是屏幕和输入设备驱动程序(关于键盘或鼠标)来与实际硬件交互。在
中间层,可移植的图形引擎提供对线的绘制、区域的填充、多边形、裁剪以
及颜色模型的支持。
在最上层,Microwindows支持两种API:Win32/WinCE API实现,称为
Microwindows;另一种API与GDK非常相似,它称为Nano-X。Nano-X用在linux
上。它是象X的API,用于占用资源少的应用程序。
Microwindows支持1、2、4 和8bpp(每像素的位数)的palletized显示
,以及 8、16、24和32bpp的真彩色显示。Microwindows还支持使它速度更快的帧缓冲区。Nano-X服务器占用的资源大约在100K到150K字节。

原始Nano-X应用程序的平均大小在30K到60K。由于Nano-X是为有内存限制的低端设备设计的,所以它不象X那样支持很多函数,因此它实际上不能作为微型X(Xfree86)的替代品。

可以在Microwindows上运行FLNX,它是针对Nano-X而不是X进行修改的 FLTK(快速轻巧工具箱(Fast Light Toolkit))应用程序开发环境的一个版本。本章将在后面描述FLTK。
Nano-X 的优点包括:
与Xlib实现不同,Nano-X仍在每个客户机上同步运行,这意味着一旦发送了客户机请求包,服务器在为另一个客户机提供服务之前一直等待,直到整个包都到达为止。这使服务器代码非常简单,而运行的速度仍非常快;
占用很小的资源。

Nano-X 的缺点包括:
联网功能部件至今没有经过适当地调整(特别是网络透明性);
还没有太多现成的应用程序可用;
与X相比,Nano-X虽然近来正在加速开发,但仍没有那么多文档说明而且没有很好的支持,但这种情形应该会有所改变。

6.3 OpenGUI
OpenGUI在linux系统上存在已经很长时间了。最初的名字叫FastGL,只支持 256的线性显存模式。但目前也支持其他显示模式。这个库是用C++编写的,只提供 C++ 接口。

6.4 Qt/Embedded
Qt/Embedded是Trolltech新开发的用于嵌入式linux的图形用户界面系
统。Trolltech最初创建Qt作为跨平台的开发工具用于linux台式机。它支持
各种有UNIX特点的系统以及Microsoft Windows。KDE — 最流行的linux 桌
面环境之一,就是用Qt编写的。
Qt/Embedded以原始Qt为基础,并做了许多出色的调整以适用于嵌入式环
境。Qt Embedded通过Qt API与linux I/O设施直接交互。那些熟悉并已适应
了面向对象编程的人员将发现它是一个理想环境。而且,面向对象的体系结
构使代码结构化、可重用并且运行快速。与其它GUI相比,QtGUI非常快,并
且它没有分层,这使得Qt/Embedded成为用于运行基于Qt的程序的最紧凑的环
境。
Trolltech还推出了Qt掌上机环境(Qt Palmtop Environment,俗称Qpe
)。Qpe提供了一个基本桌面窗口,并且该环境为开发提供了一个易于使用的
界面。Qpe包含全套的个人信息管理(Personal Information Management (PIM)
)应用程序、因特网客户机、实用程序等等。然而,为了将Qt/Embedded或Qpe
集成到一个产品中,需要从Trolltech获得商业许可证。(原始Qt自版本 2.2
以后就可以根据 GPL 获得 。)
它的优点包括:
面向对象的体系结构有助于更快地执行 ;
占用很少的资源,大约800K;
抗锯齿文本和混合视频的象素映射;
它的缺点是:
Qt/Embedded和Qpe只能在获得商业许可证的情况下才能使用。

6.5 MiniGUI 简介
MiniGUI是近几年国人自己开发的一种面向嵌入式系统或者实时系统的图形用户界面支持系统。当初设计的初衷是面向工业领域这类资源存储比较紧张又需要快速响应的场合。它主要运行于linux控制台,实际可以运行在任何一种具有POSIX线程支持的POSIX兼容系统上。MiniGUI刚诞生时是免费的,现在也需要购买商业许可证。MiniGUI的优点包括:小巧,包含全部功能的库文件大小为300k左右;运行速度快;可根据项目需求进行定知和配置。MiniGUI的缺点有:控件制作比较粗糙;需要商业许可证。
7
图形化的开发工具FLTK
FLTK是一个简单但灵活的GUI工具箱,它在linux世界中赢得越来越多的关注,它特别适用于占用资源很少的环境。它提供了您期望从GUI工具箱中获得的大多数窗口构件,如按钮、对话框、文本框以及出色的“赋值器”选择(用于输入数值的窗口构件)。还包括滑动器、滚动条、刻度盘和其它一些构件。

针对 Microwindows GUI引擎的FLTK 的linux版本被称为FLNX。FLNX由两个组件构成:Fl_Widget和FLUID。Fl_Widget由所有基本窗口构件API组成。FLUID(快速轻巧的用户界面设计器(Fast Light User Interface Designer, FLUID))是用来产生FLTK源代码的图形编辑器。总的来说,FLNX是能用来为嵌入式环境创建应用程序的一个出色的UI构建器。

Fl_Widget占用的资源大约是40K到48K,而FLUID(包括了每个窗口构件)大约占用380K。这些非常小的资源占用率使Fl_Widget和FLUID在嵌入式开发世界中非常受欢迎。
优点包括:
习惯于在象Windows这样已建立得较好的环境中开发基于GUI的应用程序的任何人都会非常容易地适应FLTK环境;
它的文档包括一本十分完整且编写良好的手册;
它使用LGPL进行分发,所以开发人员可以灵活地发放他们应用程序的许可证;
FLTK是一个C++库(Perl和Python绑定也可用)。面向对象模型的选择是一个好的选择,因为大多数现代GUI环境都是面向对象的;这也使将编写的应用程序移植到类似的API中变得更容易;
Century Software的环境提供了几个有用的工具,诸如ScreenToP和ViewML浏览器。

它的缺点是:
普通的FLTK可以与X和Windows API一同工作,而FLNX不能。它与X的不兼容性阻碍了它在许多项目中的使用。

嵌入式linux开发正如火如荼地迅速发展着。作为一个开发者,每天都会
接触到各种新鲜的软件的知识,必须不断地从中学习,丰富自己的知识,拓
展自己的眼界。在开发过程中,从引导装载程序和分发版到文件系统和GUI中
的每一个事物的各种选项中作出选择。Linux上的嵌入式开发已经达到了新的
境界,并且调整模块以适合您的规范从未比现在更简单。这已经导致出现了
许多时新的手持和微型设备作为开放盒,这是件好事 — 因为事实是您不必
成为一个专家从这些模块中进行选择来调整您的设备以满足您自己的要求和
需要。
我们希望以上对嵌入式linux领域的介绍性概述能激起您进行试验的欲
望,并且希望您将体会摆弄微型设备的乐趣以满足您的爱好。就从现在开始

页: [1]
查看完整版本: 嵌入式linux系统开发概述