裁减 Linux 嵌入式系统:方法与实例 (rev#2)
裁减 Linux 嵌入式系统:方法与实例(rev#2)原PDF:《縮減Linux嵌入式系統軟體: 方法與實例 》作者:梁元彪 林盈达 刘建文整理(http://blog.csdn.net/keminlau) KEY:嵌入式操作系统 裁减 linux embedded 国立交通大学资讯科学系 300 新竹市大学路 1001 号 Tel: 03-571212
裁减 Linux 嵌入式系统:方法与实例(rev#2)
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
更多推荐
所有评论(0)