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与根文件系统的关系。你看一眼就能明白整个流程:

Busybox与最小根文件系统构建流程 Busybox源码 make menuconfig make && make install 最小根文件系统 /dev 设备节点 /etc 配置文件 /proc /sys /tmp 临时目录 系统启动成功

你看,整个流程其实不复杂。从源码到配置,再到编译安装,最后搭出根文件系统。每一步都有章可循。

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)存在

嗯,到这里,你已经亲手搭建了一个最小根文件系统。别看它小,五脏俱全。后续的课程里,我们会在这个基础上不断加东西——添加库、增加应用、优化启动速度。但今天这一步,是地基。

可可精品资料库