2. Busybox初探:Busybox是什么、下载与编译、生成最小根文件系统
说实话,很多刚入行做嵌入式Linux的朋友,第一次接触根文件系统时都会有点懵。我当时也一样——明明内核都跑起来了,怎么系统还是没法用?后来才明白,缺的就是这个“根文件系统”。而Busybox,就是搭建它的核心工具。
2.1 Busybox到底是什么?
Busybox,江湖人称“嵌入式瑞士军刀”。它把Linux里常用的命令(比如ls、cp、mv、ps、mount等)全部打包成一个可执行文件。你想想看,原本每个命令都是一个独立的程序,体积不小。Busybox把它们合并了,体积能小到几百KB。
我在项目中遇到过最极端的情况——一个Flash只有4MB空间,内核占了2MB,留给根文件系统的只剩2MB。如果用完整的GNU工具集,根本塞不下。Busybox就是来救场的。
核心特点:
- 单个可执行文件,体积极小
- 支持超过300个常用Linux命令
- 高度可裁剪,按需编译
- 静态或动态链接均可
2.2 下载Busybox源码
我个人习惯从官网下载稳定版本。Busybox的版本号策略很简单——偶数版本是稳定版,奇数版本是开发版。比如1.36.x是稳定版,1.37.x就是开发版。生产环境,我建议用稳定版。
# 下载最新稳定版
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
# 解压
tar -xjf busybox-1.36.1.tar.bz2
cd busybox-1.36.1/
嗯,这里要注意:如果你在公司内网开发,可能没法直接连外网。我一般会提前下载好,放到一个共享目录里。或者用git克隆镜像仓库也行。
2.3 配置与编译
Busybox的配置方式和Linux内核很像。它也有一个menuconfig界面,你可以选择要编译哪些命令、用什么编译选项。
# 先加载默认配置
make defconfig
# 然后进入菜单配置
make menuconfig
进入menuconfig后,你会看到类似内核配置的界面。我个人习惯先做这几步:
- 静态编译:在
Settings → Build static binary (no shared libs)勾上。这样生成的busybox不依赖动态库,放到任何系统都能跑。 - 交叉编译:在
Settings → Cross compiler prefix设置你的交叉编译工具链前缀,比如arm-linux-gnueabihf-。 - 安装路径:在
Settings → Destination path for 'make install'设置一个空目录,比如./_install。
小技巧: 如果你不确定需要哪些命令,先用defconfig。它默认开启了大部分常用命令。等系统跑起来了,再回头裁剪。
配置完成后,直接编译:
# 编译(-j后面的数字是CPU核心数,根据你的机器调整)
make -j4
# 安装到指定目录
make install
编译完成后,看看 _install 目录里有什么:
ls -l _install/
# 你会看到 bin/ sbin/ usr/ linuxrc
这个 linuxrc 是个符号链接,指向 bin/busybox。系统启动时,内核会先执行它。
2.4 生成最小根文件系统
有了Busybox,我们就能搭建一个能用的根文件系统了。但光有命令还不够,还需要一些基础目录和配置文件。
我曾经踩过一个坑——编译完Busybox后,直接把它扔到分区里,结果启动时提示 can't open /dev/null。说白了,就是缺了设备节点。
一个最小根文件系统至少需要这些:
| 目录/文件 | 说明 |
|---|---|
| /bin, /sbin, /usr | Busybox安装的命令 |
| /dev | 设备节点(至少需要console、null、zero) |
| /etc | 配置文件(至少需要inittab) |
| /proc, /sys | 虚拟文件系统挂载点 |
| /tmp | 临时文件目录 |
我们来手动搭建一个:
# 创建目录结构
mkdir -p rootfs/{bin,sbin,usr,dev,etc,proc,sys,tmp,lib}
# 复制Busybox
cp -a _install/* rootfs/
# 创建设备节点(需要root权限)
sudo mknod rootfs/dev/console c 5 1
sudo mknod rootfs/dev/null c 1 3
sudo mknod rootfs/dev/zero c 1 5
# 创建inittab文件
cat > rootfs/etc/inittab << "EOF"
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
EOF
# 创建初始化脚本
mkdir -p rootfs/etc/init.d
cat > rootfs/etc/init.d/rcS << "EOF"
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t tmpfs none /tmp
EOF
chmod +x rootfs/etc/init.d/rcS
注意: 设备节点的主次设备号不能写错。console是5:1,null是1:3,zero是1:5。写错了系统启动时会报错。
到这里,一个最小根文件系统就搭好了。你可以把它打包成cpio归档,或者直接放到分区里测试。
2.5 知识体系总览
下面这张图,是我自己总结的Busybox与根文件系统的关系。你看一眼就能明白整个流程:
你看,整个流程其实不复杂。从源码到配置,再到编译安装,最后搭出根文件系统。每一步都有章可循。
2.6 验证你的根文件系统
怎么知道搭的对不对?我一般用QEMU模拟器快速验证。不需要真硬件,省时省力。
# 打包成cpio归档
cd rootfs
find . | cpio -o --format=newc > ../rootfs.cpio
# 用QEMU启动(假设你有内核镜像)
qemu-system-arm -M versatilepb \
-kernel vmlinuz \
-initrd rootfs.cpio \
-append "console=ttyAMA0" \
-nographic
如果一切正常,你会看到Busybox的init进程启动,然后出现一个shell提示符。输入 ls、ps 这些命令,都能正常工作。
验证清单:
- 系统能正常启动到shell
- 常用命令(ls、cp、mv、cat)可用
- /proc和/sys挂载正常
- 设备节点(console、null)存在
嗯,到这里,你已经亲手搭建了一个最小根文件系统。别看它小,五脏俱全。后续的课程里,我们会在这个基础上不断加东西——添加库、增加应用、优化启动速度。但今天这一步,是地基。
可可精品资料库