使用BusyBox, 在为目标系统所构建的根文件系统中添加应用程序就易如反掌了. 想象一下:单独得交叉编译每个UNIX/Linux应用程序的工作量是多么恐怖. |
BusyBox 可以与glibc或uClibc库进行链接编译, 可以采用动态链接或静态链接(配置选项中可选).即便采用与glibc的静态链接,最终生成的busybox文件大小也能轻易控制在1MB之内(在配置BusyBox时不要选择不需要的功能).而采用uClibc动态链接的可执行文件就更小了. 这非常适于存储空间紧张的嵌入式Linux系统. 由此,有人将BusyBox称为嵌入式系统中的瑞士军刀. 更为形象的比喻是: Linux系统中的单个命令是电路中的分立式元件,而BusyBox是将它们集成在一起的IC: 功能不变, 体积却大为减小.
本文讨论BusyBox的编译, 安装. 包括安装到本地主机和安装到ARM目标系统中.
配置BusyBox
配置BusyBox和配置Linux内核的方法很类似, 思想也大同小异: 也是基于源码树目录中的.config文件来进行的.还是推荐使用menuconfig配置工具.
下面的工作都是在解压后的BusyBox源码树根目录中进行的.
$ makedefconfig: 针对大多数用户的默认配置
$ makeallnoconfig: 全不选
$ makeallyesconfig : 全选
一般先make deconfig, 然后再使用menuconfig进行配置.
$ make help查看BusyBox的make选项帮助. |
如同配置Linux内核, 你也可以使用既有的.config(可更改其命名)文件. 可以在menuconfig中加载,输出配置文件.
下面列出一些值得注意的配置选项:
BusyBoxSettings
BuildOptions:
Build BusyBox as a staticbinary (no shared libs) : 将BusyBox动态链接或静态连接.
- Do you want to buildBusyBox with a Cross Compiler? : 选择交叉编译器.
InstallationOptions:
默认地, 运行 make install之后, BusyBox将被安装到./_install目录.
配置根据具体需要来: 不需要的不选.
- NFS是肯定要选的, 使用NFS将宿主机的文件系统mount到目标板上,这是嵌入式Linux程序开发的一个重要方面.
- 由于可使用NFS, 能在宿主机上实现的功能就都不需要在目标板上实现了.
- Debian Utilities 全不选, Editors全不选, System LoggingUtilities全不选.
- 解压缩工具只安装解压工具. 而且只选择一种: bzip2相关的,以及tar工具(只要求目标板能解压缩tar.bz2文件).
- shell使用ash.
编译BusyBox
完 成对BusyBox的配置工作后, 就可以编译, 安装它了. BusyBox可用于多种体系结构的CPU.这里分别介绍用于本机系统的BusyBox和用于ARM目标系统的BusyBox. 另外,BusyBox可与glibc或uClibc动态或静态连接. 下面分情况介绍:
用于本机的BusyBox
用于本机的BusyBox编译过程很简单, 只需运行make就可以了.
交叉编译BusyBox
交叉编译BusyBox与编译用于本地系统的BusyBox大同小异, 唯一的区别是它需要使用交叉编译工具. 另外要注意库的链接方式:如果目标系统中没有某库, 那么BusyBox应该与该库静态链接. 编译步骤如下:
1, 修改PATH变量:
$ exportPATH=<交叉编译工具所在目录>:$PATH
2, 在调用make命令时候要指定TARGET_ARCH和CROSS变量.
$ make TARGET_ARCH=armCROSS=arm-linux-
新版的BusyBox可以在配置过程中设定交叉编译工具. 这样,为目标系统编译BusyBox的make命令和为本地主机编译BusyBox没有任何区别! |
我这里使用Scratchbox来针对ARM目标系统编译BusyBox. (可参考本blog的:使用Scratchbox来开发嵌入式Linux).安装scratchbox之后, 可以在对scratchbox进行配置时安装各种交叉编译工具:arm-linux-gcc(与glibc链接),arm-linux-uclibc-gcc(与uclibc链接),它还可以为本地系统(x86)安装与uclibc链接的gcc. 这样你直接指定相应的编译器既可.不需要另外安装uClibc库.
为了加快编译速度, 可以修改Makefile, 将CC="$(HOSTCC)"改为CC="ccache $(HOSTCC)".同时也可使用 $ make -j2用2个任务来进行编译过程. |
实例
下面以几个例子来介绍BusyBox的编译方法:
1,针对本地主机编译与glib链接的BusyBox
由于GNU/Linux系统中都装有glibc, 所以可以不使用Scratchbox提供的编译器. 而且,可以将BusyBox配置为与glibc库动态链接. 其他选项均设为默认.
$ makedefconfig; 默认配置
$ makemenuconfig ; 选择与glibc动态链接
$ make-j2
$ make install
可以使用ls -l, file命令查看生成的busybox可执行文件相关信息. 注意,在源码树根目录同时还生成了busybox_unstripped文件, 将它strip之后即得到busybox.
默认配置, 与glibc动态连接后的busybox大小为: 858K
2, 针对本地主机编译与uClibc链接的BusyBox
我 没有另外地在本地主机上安装uClibc, 而是使用Scratchbox提供的编译工具:i386-gcc-3.3.2-uclibc-snapshot-20040229. 由于本地主机上没有uClibc库,所以将busybox与uClibc库静态链接. 其他选项设为默认
$ export PATH=/home/zp/project/sb/scratchbox/compilers/i386-gcc-3.3.2-uclibc-snapshot-20040229/bin:$PATH
$ makemenuconfig
$ makeCROSS=i386-linux-uclibc--j2
$ makeinstall
默认配置, 与uClibc静态链接后的busybox大小为: 1.1M
3,针对ARM目标系统编译与glibc动态连接的BusyBox
使用Scratchbox中提供的arm-linux-gcc交叉编译工具. 这里没有使用默认配置,而是只选择我认为需要的功能.
$ exportPATH=/home/zp/project/sb/scratchbox/compilers/arm-linux-gcc3.4.cs-glibc2.3/bin:$PATH
$ makemenuconfig
$ make CROSS=arm-linux--j2
$ makeinstall
剔除了不需要的内容, 与glibc动态链接后的busybox大小为: 382K
4,针对ARM目标系统编译与uClibc静态连接的BusyBox
使用Scratchbox中提供的arm-linux-uclibc-gcc交叉编译工具. 这里没有使用默认配置,而是只选择我认为需要的功能.
$ exportPATH=:/home/zp/project/sb/scratchbox/compilers/arm-linux-gcc3.4.cs-uclibc0.9.27/bin$PATH
$ makemenuconfig
$ make CROSS=arm-linux-uclibc-j2
$ makeinstall
剔除了不需要的内容, 与uClibc静态链接后的busybox大小为: 509K
注意: 针对ARM目标系统编译BusyBox时, 可在menuconfig中选择特定的交叉编译器.这样就make命令就和为本地主机编译BusyBox一样了, 不需要更改PATH和CROSS变量. |
安装,运行BusyBox
编译完成后, 输入 $ makeinstall 进行BusyBox的安装.
默认地, BusyBox将在当前目录(也就是BusyBox源码树根目录)新建一个名为"_install"的目录.BusyBox将被安装到其中. 可以在配置BusyBox时设定安装目录.
完成安装之后, 在./_install目录中有下列文件和目录:
binlinuxrc sbin usr
其 中linuxrc, bin, sbin, usr目录中的包含一些我们熟悉的位于PC机/bin, /sbin, /usr/bin,/usr/sbin目录中的程序.而BusyBox安装的这些程序都是指向busybox文件(位于./_install/bin目录)自身的符号连接.
运行BusyBox"安装"的这些程序时候, 实际上都是在调用busybox这个单独的程序. 比如: $ ./ls -l , 实际向busybox传递了2个参数: ls和-l. 前面的命令等价于$ ./busybox ls-l.
针对前面编译实例中安装的BusyBox,我们分别讨论针对本地主机编译的BusyBox和针对ARM目标系统编译的BusyBox.
本地主机
很简单, 可以直接调用busybox, 也可以调用连接到它的符号连接. 当然, 可以修改PATH变量来直接调用它们.
$ ./busybox ls -l
$ ./ ls -l
ARM目标系统
可以使用仿真工具来运行. 这里使用qemu. 在Debian/Ubuntu中安装qemu: $ sudo apt-get install qemu
$ qemu-arm ./busybox ls-l
这里有个问题, 如果busybox是与C库动态链接的(哪怕是和glibc库动态链接), 那么运行它是将会产生段错误:
Unable to loadinterpreter
Segmentation fault (coredumped)
如果采用静态链接, 则没有问题.
BusyBox还提供与init类似的功能, 也非常适用与嵌入式系统. |
参考资料
1, http://www-128.ibm.com/developerworks/cn/linux/l-busybox/index.html
2, 《构建嵌入式Linux系统》第6章.
3, http://free-electrons.com/training/devtools
4, busybox命令: http://www.busybox.net/downloads/BusyBox.html