BusyBox (
http://www.busybox.net)将数以百计的常用Unix/Linux命令集成到一个可执行文件中(名为busybox).它体积小巧, 功能却不失强大. 常用Linux命令实现的功能它都能提供. 它甚至还提供了tftp, http服务程序. 尽管少数的Linux命令的某些选项BusyBox没能提供, 但这并不影响它在嵌入式Linux系统中的流行.
使用BusyBox, 在为目标系统所构建的根文件系统中添加应用程序就易如反掌了. 想象一下: 单独得交叉编译每个UNIX/Linux应用程序的工作量是多么恐怖.
BusyBox可以与glibc或uClibc库进行链接编译, 可以采用动态链接或静态链接(配置选项中可选). 即便采用与glibc的静态链接, 最终生成的busybox文件大小也能轻易控制在1MB之内(在配置BusyBox时不要选择不需要的功能). 而采用uClibc动态链接的可执行文件就更小了. 这非常适于存储空间紧张的嵌入式Linux系统. 由此, 有人将BusyBox称为嵌入式系统中的瑞士军刀. 更为形象的比喻是: Linux系统中的单个命令是电路中的分立式元件, 而BusyBox是将它们集成在一起的IC: 功能不变, 体积却大为减小.
本文讨论BusyBox的编译, 安装. 包括安装到本地主机和安装到ARM目标系统中.
配置BusyBox
配置BusyBox和配置Linux内核的方法很类似, 思想也大同小异: 也是基于源码树目录中的.config文件来进行的. 还是推荐使用menuconfig配置工具.
下面的工作都是在解压后的BusyBox源码树根目录中进行的.
$
make defconfig : 针对大多数用户的默认配置
$
make allnoconfig : 全不选
$
make allyesconfig : 全选
一般先make deconfig, 然后再使用menuconfig进行配置.
$
make help 查看BusyBox的make选项帮助.
如同配置Linux内核, 你也可以使用既有的.config(可更改其命名)文件. 可以在menuconfig中加载, 输出配置文件.
下面列出一些值得注意的配置选项:
BusyBox Settings
Build Options: Build BusyBox as a static binary (no shared libs) : 将BusyBox动态链接或静态连接.
- Do you want to build BusyBox with a Cross Compiler? : 选择交叉编译器.
Installation Options:默认地, 运行 make install之后, BusyBox将被安装到./_install目录.
配置根据具体需要来: 不需要的不选.
- NFS是肯定要选的, 使用NFS将宿主机的文件系统mount到目标板上, 这是嵌入式Linux程序开发的一个重要方面.
- 由于可使用NFS, 能在宿主机上实现的功能就都不需要在目标板上实现了.
- Debian Utilities 全不选, Editors全不选, System Logging Utilities全不选.
- 解压缩工具只安装解压工具. 而且只选择一种: 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变量:
$
export PATH=<交叉编译工具所在目录>:$PATH2, 在调用make命令时候要指定TARGET_ARCH和CROSS变量.
$
make TARGET_ARCH=arm CROSS=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库动态链接. 其他选项均设为默认.
$
make defconfig ; 默认配置
$
make menuconfig ; 选择与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 $
make menuconfig $
make CROSS=i386-linux-uclibc- -j2 $
make install 默认配置, 与uClibc静态链接后的busybox大小为: 1.1M
3, 针对ARM目标系统编译与glibc动态连接的BusyBox使用Scratchbox中提供的arm-linux-gcc交叉编译工具. 这里没有使用默认配置, 而是只选择我认为需要的功能.
$
export PATH=/home/zp/project/sb/scratchbox/compilers/arm-linux-gcc3.4.cs-glibc2.3/bin:$PATH$
make menuconfig $
make CROSS=arm-linux- -j2 $
make install 剔除了不需要的内容, 与glibc动态链接后的busybox大小为: 382K
4, 针对ARM目标系统编译与uClibc静态连接的BusyBox使用Scratchbox中提供的arm-linux-uclibc-gcc交叉编译工具. 这里没有使用默认配置, 而是只选择我认为需要的功能.
$
export PATH=:/home/zp/project/sb/scratchbox/compilers/arm-linux-gcc3.4.cs-uclibc0.9.27/bin$PATH$
make menuconfig $
make CROSS=arm-linux-uclibc -j2 $
make install 剔除了不需要的内容, 与uClibc静态链接后的busybox大小为: 509K
注意: 针对ARM目标系统编译BusyBox时, 可在menuconfig中选择特定的交叉编译器. 这样就make命令就和为本地主机编译BusyBox一样了, 不需要更改PATH和CROSS变量.
安装, 运行BusyBox
编译完成后, 输入 $
make install 进行BusyBox的安装.
默认地, BusyBox将在当前目录(也就是BusyBox源码树根目录)新建一个名为"_install"的目录. BusyBox将被安装到其中. 可以在配置BusyBox时设定安装目录.
完成安装之后, 在./_install目录中有下列文件和目录:
bin linuxrc 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 -lARM目标系统可以使用仿真工具来运行. 这里使用
qemu. 在Debian/Ubuntu中安装qemu: $
sudo apt-get install qemu$
qemu-arm ./busybox ls -l这里有个问题, 如果busybox是与C库动态链接的(哪怕是和glibc库动态链接), 那么运行它是将会产生段错误:
Unable to load interpreterSegmentation fault (core dumped)如果采用静态链接, 则没有问题.
BusyBox还提供与init类似的功能, 也非常适用与嵌入式系统.