现在的位置: 首页 > 综合 > 正文

裁减 Linux 嵌入式系统:方法与实例

2013年07月16日 ⁄ 综合 ⁄ 共 8037字 ⁄ 字号 评论关闭

裁减 Linux 嵌入式系统:方法与实例

作者:梁元彪 林盈达
刘建文整理(http://blog.csdn.net/keminlau 

KEY:嵌入式操作系统 裁减 linux embedded

国立交通大学资讯科学系

300 新竹市大学路 1001 号

Tel: 03-5712121 ext. 56667 Fax: 03-5712121 ext. 59263 {upleong , ydlin}@cis.nctu.edu.tw 联络人 : 梁元彪

摘要

开源(开放源代码)的迅速发展,正逐步渗透至嵌入式系统,两者的结合将成为后个人电脑时代中极为重要的一环。首先我们在此探讨使用 Linux 作为嵌入式操作系统的方法,透过如何对内核 (kernel) ,守护进程 (daemons) ,程序库 (libraries) 和应用程序 (applications / utilities) 等四个主要部份,进行裁减其大小后,以便配置在以闪存为储存设备的嵌入式系统中。接着以提供 VPN 、防火墙、入侵侦测系统 (IDS) 等功能的安全网关 [1] 作为例子,说明如何建立一个完整的嵌入式 Linux 系统。最后我们把拥有以上所有功能的安全网关,从使用 Redhat 的系统 ( 约 1.3 GBytes) 以及额外的 RPM 套件 ( 约 15 Mbytes) ,成功裁减系统 至 19 Mbytes 。经压缩为 7 Mbytes 后,置于配备 64M 内存与 8M 闪存的系统中。

关键字 : embedded , Linux , downsizing

1. 背景

嵌入式系统 (embedded system) 已在无形中, 慢慢融入我们日常生活里。各式各样的数码相机, 个人数码助理,寛频上网用的 ADSL 或缆线数据机等,全都依赖着程序的控制。在这些的例子中, 我们可以发现,它们都拥有特定的功能,运作稳定而且非常普遍。这就是嵌入式系统的威力,使用的资源少,稳定度高,价格低。挟着众多的优点,嵌入式系统将成为后个人电脑时代的重要产品技术。在表 1 中,列举了一般个人电脑与嵌入式系统在资源与功能上的差异。嵌入式系统所用的储存设备为闪存,比硬盘耐用但容量很小。其次会省去 VGA 等不必要的设备。最主要的是在功能上,嵌入式系统的功能特定,所以能对其最优化,也易于进行测试,并且大大提高软件在系统中的稳定度。

就网络设备而言,功能全面,稳定与互通性等因素,是极重要的关键。在开放式软件蓬勃发展以前,市场多为商业软件所占有,直至 Linux 等操作系统的崛起,在网络领域上已成为极佳的选择之一。表 2 对 Linux 与各厂商提供的操作系统做了一个简单的比较。我们可以看到商业软件的价格高昂,并且有收取权利金的制度。另外每家厂商提供的软件大多并不相容,操作系统也属于封闭式,所以一般程序对其支持比较缺乏,严重依赖厂商的提供。嵌入式 Linux 提供了源代码,与一般 UNIX 系统的应用程序相容,以及完全自由取得等优势,皆对各历史悠久的系统造成威胁。然而,正因为还在起步阶段,目前的嵌入式 Linux 版本并算不上是一套非常简洁的系统。如何善用与分配资源,整合一般 Unix 的程序,以及裁减系统至适合嵌入式应用成为最主要的目标。

接下来先了解具有高度弹性的 Linux ,有那些主要可被裁减的部份。再分析裁减至嵌入式版本的方法及其开发工具。在本文的最后,以安全网关为例子,介绍其功能规格和所使用的套件,并呈现经过上述裁减过程并移植至嵌入式系统后,其显著的成效。

2. 可裁减的部份

Linux 软件不断的发展,累积越来越多的应用程序,形成相同功能程序有多种选择的优势。而我们需要的是一个精简的系统,因此必须进行裁减。首先把庞大的系统归纳为四个部份 -- 内核 (kernel) ,守护进程 (daemons) ,程序库 (libraries) ,应用和工具程序 (applications and utilities) 。我们在进行裁减的原则是在不直接删改程序码,以保有源代码的完整性。表 3 列出裁减各子系统的方向与目标,以下为详细的介绍。

2.1 内核

因为嵌入式系统的功能规格定义明确,在内核的配置中只须留下必要的选项或模块等,其他不必要的都可以舍弃。另一种就是利用取代的方式。如果是网络设备,可以把 console 的输出以串口来取代显示卡的输出。借此不单可省下硬件成本,更可在 Linux 2.4 的内核中省下 42KB 的空间。除此以外,并口,即插即用,软驱,光驱,键盘,滑鼠, USB 等驱动程序都可以被省略。

2.2 守护进程

在开源的影响下,各程序除了往更完整功能迈进的同时,对各种软硬件的支持亦渐趋多元化。然而在有限的资源下,必须根据需求,重新定义各程序所需要的功能,而应避免安装原本可直接执行的软件包。举例来说,如果只使用 Squid 作为 http proxy ,而并没用到其 caching 的功能。就可在编译时,直接利用 Squid 的配置程序,关掉对文件系统的支持 ( 使用选项 --enable-storeio=null) 。这样在 Squid 2.4.Stable1 的版本中,所得到的程序码,便可省掉 145KB ( 约 26%) 之多。其他像 GNU Zebra 这些网络相关的程序,也可以把 IPv6 的支持关掉以节省空间。

2.3 程序库

  程序使用静态或动态连接,会产生不一样的特性。静态连接使得程序执行时 overhead 减少,程序码也比较简洁。而动态连接则随共用程序库的程序数目增加而节省大量的空间。因此必需根据需求在两者之间取得平衡,如果程序库只有一支程序在用,便可考虑选择使用静态连接。而使用动态连接的情况下,可以利用工具程序 ldd 来检查程序与程序库间的相依关系。藉由此法,便可找出及保留系统所需的共用程序库的最小集合。

2.4 应用和工具程序

在这个部份就具有更多的弹性了,因为这类程序的选择性多,且可用多种方法替代。以内核为例,透过对 /proc 的支持,便可以读取或修改多项系统的参数配置,不必再使用累赘或不常用的工具程序。例如只要读取 ARP table 时,便可使用指令 #cat /proc/net/arp 来达成,省却使用 /sbin/arp 这支程序,完全不占空间。其次在嵌入式系统上,用户不再是一般 PC 使用者,简化程序界面,在线帮助,甚至简化程序功能等,都可以实现精简化的效果。 BusyBox[2] 就是其中具有代表性的一套工具程序,它以单一的小程序,十分精简地提供了文件工具, shell ,文字处理,压缩程序等 UNIX 中常用的功能。表格 4 列出 BusyBox 与 tinylogin[3] 的功能及其相对原工具程序的大小。由此可见充份利用专为嵌入式系统而设计的工具,是一个取得双赢的好方法。

2.5 调试信息与符号表 (Symbol Table)

   在调试阶段结束后,在程序内用于调试的信息,全部都可以被删掉,因为它们都提供配合源代码调试的功能,所以占了很大的空间,可以使用工具程序 strip 删去。以 IDS 的 snort daemon 和 squid daemon 为例,分别从 969K 与 670K ,减至 307K 与 419K 。此以,我们也可以对所有执行文件进行扫瞄,找出在共享程序库中没有被用到的符号列表,将它们从程序库使用 strip 移除,进一步达到裁减系统的目的。

3. 如何进行裁减

3.1 进行方式

目前 Linux 的发行版本 (distribution) 众多,各有优缺点,要集各家之大成,建立一套属于自己的嵌入式 Linux 并非梦想,只要根据适当的方法进行就可以。首先以 Redhat 7.1 的发行版本来看,完整安装服务器的版本,约须 1.3 GBytes 以上的空间,这还不包含一些特别的软件包。然而,在众多的软件中,我们只要其中的一小部份,可能在 10~30 MBytes 之间。进行的方式必须有效率的建立系统,基本可行的方法有两种 :

(1) 从其中一个发行版本中把不必要的部份全部删掉,留下我们想要的系统。

(2) 把系统所有的功能依规格从新建立起来。

正如前所述,我们必须先对系统功能规格清楚了解,才能进行裁减系统的动作。从图 1 可见,使用方法一,会有多达几百 Mbytes 不必要的数据在旁影响。使用方法二,则可以很直接的建立一个从 2MB 至 16MB 大小的嵌入式系统。所以使用重建的方法,显然是比较好的选择,要使用此方式前,得先准备三件事 -- 整体功能规格,使用的软件包,目标平台的规格。其实这三者之间息息相关,也就是从三个不同的角度去定义系统的做法,使其更全面更准确。

3.2 开发环境

在清楚了解准备建立的系统后,便可开始利用 Linux 打造嵌入式的设备了。首先我们必须区 分开发平台与目标平台。目标平台就是程序最后被移植及执行的地方,因为资源有限,开发与调试的环境都会集中开发平台上。表 5 列出两个平台上的主要开发工具。

要建立一个最基本的发展环境,必需具备一套跨平台的发展工具 (Cross Development Kit) ,包含有编译器 [4] ,连接器,调试器等。另外还要准备制作文件系统所需的程序。而目标平台上,只需准备一段系统开机程序,如 etherboot[5] , redboot[6] 等。此程序可以在调试阶段时,从网络取得系统映像档 (image) 后启动,或是直接从闪存中,把系统启动。一旦启动后,就进入 Linux 的操作系统,同时亦可使用 GDB server 作为远端调试的工具。

3.3 开发过程

开发的过程如图 2 所示,可以分为几个部份。首先要准备 Linux 的内核,配上根目录所在的文件系统,再加上守护进程程序和应用程序等,经过压缩后,打包成一个含有内核的映像文件。目标平台透过网络或闪存,取得映像文件后,进行解压缩,经过系统启动,初始化后,就是一台使用嵌入式 Linux 为操作系统的机器。

建立文件架构的时候,必须注意权限的配置。因为闪存的可覆写次数有限 ( 约为一百万次 ) ,所以会以只读的方式挂上 (mount) 系统。而 /var /dev 等目录须为可读写的,或是记录一些暂存文件和记录文件等,都可以利用系统的内存空间来模拟可写入的文件系统 (RAM disk) ,但。透过建立符号化连结 (symbolic link) 取得写入权限,余下的则由只读的方式被保护在闪存之上。如果大量的记录文件必须在关机后留下的话,外挂硬盘至系统 /var/log 是比较适当的做法。小量的记录文件是可以写入闪存中,但一定要使用缓冲,否则频繁的写入会使其使用寿命缩短。同理,我们也不可能使用 swap ,若然内存实在不足的情况下,可以考虑系统留在闪存上,同样以外加硬盘机作为 swap disk 的功能。在嵌入式系统中,会配合 ramdisk 使用在系统上,但是会与使用一般的文件系统有差别,因为 ramdisk 会使用部份内存,因此可用的内存相对减少,可能造成对内存使用状况的误解,必须特别注意。图 3 说明了使用 ram disk 时的内存空间分布状况。

4. 安全网关实例

4.1 功能简介

接下来我们以安全网关为例,说明根据上述方法开发嵌入式版本的成效。安全网关是一台具有防火墙, VPN 与入侵侦测系统的闸道器。全部皆以开源的软件组成,主要有 Linux Kernel 2.4.7[7] , netfilter (packet filter , port redirect , NAT) , Squid (URL filter)[8] , TIS (content filter)[9] , FreeS/WAN (VPN)[10] ,与 Snort (IDS)[11] 。另外还有其他的功能,如 DNS , DHCP server , routing , bandwidth management[12] , web-based configuration 等。

4.2 硬件规格

选用配备闪存的工业级电脑, CPU 为 Pentium II 350 , 64MB Ram , 8MB Flash , 10/100MbpsNIC 三张。其中程序会先压缩后放至闪存中,所以实际系统的大小可以容许超过 8Mbytes 的实体限制。

4.3 使用之主要套件及处理方式

在表 6 中列出了安全网关的主要功能中所用到的软件。

4.3.1 内核裁减过程

将内核的源代码解开后,进行配置 ( 指令 #make menuconfig 或 # make xconfig) 内核选项 (kernel options) ,其中会以串口 ( 打开 CONFIG_SERIAL , CONFIG_SERIAL_CONSOLE) 取代 VGA Console ( 关闭 CONFIG_VT , CONFIG_{VT , VGA}_CONSOLE) 以及开机时使用内存作为硬盘使用 ( 打开 CONFIG_BLK_DEV_{RAM , INITRD}) 。最后就可以编译得到新的内核 ( 指令 # make dep bzImage) 。  

4.3.2 守护进程裁减过程

我们以 Squid 守护进程作为例子。因为在安全网关上只做透通性的 http proxy 与 URL filter 服务,除了在配置文件 (squid.conf) 中把缓存功能关掉以外,可以更进一步的从程序中对缓存支持的部份删掉。在 2.4.STABLE1 的版本中,提供了三种缓存储存格式,分别是 UFS , AUFS 和 NULL ,最后一个表示不使用缓存,所以符合需求。接着使用配置程序进行设定 ( 指令 # ./configure --enable-storeio=null --enable-linux-netfilter) 并使用 Linux netfilter 模块,最后便可以进行编译。

4.3.3 程序库裁减过程

这里所指的都是对动态程序库的裁减方法,因为共用所以要考虑的是整个系统而非单一程序库。透过使用 script 程序,先找出系统内执行文件的依赖性 ( 使用 ldd , list dynamic dependencies) ,再找出执行文件与程序库间的 symbol 使用状况 ( 使用指令 #objdump –T 来检视 dynamic symbol table) ,统计所得到的结果。最后依据记录,使用程序 strip ,去除执行文件和程序库多余的部份。

4.3.4 工具程序裁减过程

使用 BusyBox 作为工具程,以简化的功能取代系统工具。首先把源代码解开,选定所需的功能,在配置文件 (busybox-0.51/Config.h) 内进行定义,如 #define BB_PING , #define BB_SLEEP , #define BB_ROUTE 等。在列举功能后,便可以进行编辑,而最后的指令,都以 symbolic link 的方式连结至 /bin/busybox 。

5. 成效之比较

在最后,依照以上所提的各种方法,分别对安全网关上不同的程序,进行裁减的过程。表 7 为一些具代表性的功能或套件,分别在两个平台上的比较,最后是裁减的比率。以这些套件来看,可以被裁减的比率达到五成。

当中可见,内核的部份把所有未用到的驱动程序拿掉以后,会裁减 11% 的大小。若要进一步缩减的话,可能就要修改部份程序,或是改以模块化的形式编译了。另外, Pluto daemon 与 TIS 都因为有大量的调试信息在内,只使用 strip symbol 的方式就有不错的成效。而 Snort 的部份可达 73% 是因为在发行版里预设支持 mysql 的数据库,使用重新配置以及去掉调试信息,就可以大幅删减了。而 web server 的部份也是在发行版中预设的多功能,而使得重新编译后裁减的比率较高。在程式库方面,则是因为已是使用的最小集合,其裁减空间只是一些未被用到的 symbol ,所以只有约 24% 的裁减比率。在最后列出的部份,包括未经处理和未分类的程序部份。其中未被处理的原因有为 -- 上述的方式皆无效,程序已经很精简,先直接使用以加速系统建立速度等。最后,若要更进一步裁减的话,可以选择直接修改程序代码,开发嵌入式的专用版本 ( 如使用 BusyBox 所提供的 API) ,整合更多功能的守护进程程序 ( 使用 Apache 提供的 proxy 取代 Squid) 等。

6. 结论

使用 Linux 作为嵌入式操作系统,是一件非常有趣的事情,因为使用者与贡献者遍布世界各地,他们都贡献出自己努力的成果,各种主要平台上都有支持的版本。可是在资源众多的情况下,却没有一个很好的集成环境,实在非常可惜。在嵌入式 Linux 中,尽管各个独立的开发工具,都已经功能完备又兼具图形使用界面,实在相当不错。然而集成开发环境这个部份,尚在起步阶段。与嵌入式操作系统 VxWorks 的开发环境相比之下,功能就显得太过简单。即使是以嵌入 Linux 为主的厂商如 Lineo[13] 的 Embedix , MontaVista[14] 的 HardHat Linux 等,都提供有不错的开发工具,唯独缺乏一个功能强悍的图形化集成环境。集成环境在功能上应以跨平台的开发环境为最重要的方向,辅以网络连线调试功能,动态下载执行模块,即时图形显示执行状态等,将会是挑战商业软件重要的里程碑。我们认为这就是开放式软件一直以来所面对的同样问题,相信如果得到解决,嵌入式 Linux 的应用必定会快速成长。除了在本文中所见,可以使用一般的 Linux 内核来实作以外,还可以有其他的选择。如不含内存管理单元 (MMU) 的 uclinux[15] 等,或是支持各种中央处理器的 ARMLinux[16 , 17] , LinuxPPC[18] 等,可根据应用的不同而作出适当的选择。希望你也可以使用嵌入式 Linux ,应用在各个不同的领域上,令无限的创意一一实现 .

7. 参考资料

[1] Ying-Dar Lin , Shao-Tang Yu , Huan-Yun Wei , 
Integrating and Benchmarking Security Gateway with 
Open Source Firewall , VPN , and IDS , submitted for 
publication , August 2001 
[2] The Swiss Army Knife of Embedded Linux , 
http://busybox.lineo.com 
[3] The worlds smallest login/passwd/getty/etc , 
http://tinylogin.lineo.com 
[4] CrossGCC Frequently Asked Questions , 
http://www.objsw.com/CrossGCC 
[5] Etherboot home page , 
http://etherboot.sourceforge.net 
[6] The Redhat Embedded Debug and Bootstrap 
firmware , http://sources.redhat.com/redboot 
[7] The Linux Kernel Archives , http://www.kernel.org 
[8] Squid Web Proxy Cache , 
http://www.squid-cache.org 
[9] The FireWall ToolKit (FWTK) from TIS , 
http://www.fwtk.org 
[10] Linux FreeS/WAN , http://www.freeswan.org 
[11] The Open Source Network Intrusion Detection 
System , http://www.snort.org 
[12] iproute2 + tc notes , 
http://snafu.freedom.org/linux2.2/iproute-notes.html 
[13] Lineo , Inc. , http://www.lineo.com 
[14] MontaVista Software , http://www.mvista.com 
[15] Embedded Linux Microcontroller Project , 
http://www.uclinux.org 
[16] armlinux.org homepage , http://www.armlinux.org 
[17] The ARM Linux Project , 
http://www.arm.linux.org.uk 
[18] The Home of the PowerPC GNU/Linux Port , 
http://www.linuxppc.org


抱歉!评论已关闭.