用Busybox制作Linux最小根文件系统

本文主要讲述使用Busybox制作Linux最小根文件系统,并使用qemu虚拟机模拟arm平台进行测试的全过程,其中包括以下几个部分内容:

  1. 环境搭建。安装qemu虚拟机,安装交叉开发工具。
  2. 编译Linux内核,生成Linux内核镜像。
  3. 编译Busybox,构建根文件系统。
  4. 使用qemu加载内核镜像和根文件系统进行测试。

环境搭建

qemu虚拟机

qemu是一个开源的模拟处理器,使用qemu,我们可以模拟出一个arm的环境用于测试。

可以直接从软件源安装

1
sudo apt install qemu

也可以上qemu官网下载最新版本自行安装

交叉编译工具

要想在宿主机(通常为x86架构)上编译出可运行于arm平台的二进制文件,需要借助交叉编译器,其用法通常是在gcc等命令前面加上平台的前缀,如arm-linux-gnueabi-gcc.

这里用从软件源直接安装

1
sudo apt-get install gcc-arm-linux-gnueabi

编译Linux内核

下载源码并解压

www.kernel.org网站上可以获取最新的稳定版内核源码。

这里我下载的是5.5.6版本的内核。下载完成后会得到一个 linux-5.5.6.tar.xz 压缩文件。将其解压到 ~/kernel/ 目录下。

1
mkdir -p ~/kernel ; tar -xvJf linux-5.5.6.tar.xz -C ~/kernel

编译

1
2
3
cd ~/kernel/linux-5.5.6/
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm vexpress_defconfig
make CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm -j4

可以在Makefile文件中添加 CROSS_COMPILE=arm-linux-gnueabi-ARCH=arm 省去每次都手动指定交叉编译选项。

编译完成后,会在~/kernel/linux-5.5.6/arch/arm/boot目录下生成zImage文件。

测试

现在,可以先用 qemu 测试一下内核的启动情况。

1
2
3
4
5
6
qemu-system-arm \
-M vexpress-a9 \
-m 1024M \
-kernel ~/kernel/linux-5.5.6/arch/arm/boot/zImage \
-dtb ~/kernel/linux-5.5.6/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
-nographic

上面命令各个参数的意义如下:

  • -M 指定硬件类型,可用 qemu-system-arm -M ? 来查看qemu支持的硬件类型。
  • -m 制定内存大小。如1024M
  • -kernel 指定内核镜像文件。
  • -dtb 指定对应硬件平台的dtb文件。
  • -nographic 无界面模式,会把虚拟系统的输出重定向到宿主机命令行。

最终,内核启动会停在下面的位置,表示尚未指定根文件系统。

1
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---

关闭qemu

关闭qemu的方法为,Ctrl-A, X.

注意:是先按下Ctrl-A,松开后按下X

构建根文件系统

下载Busybox

可以从 Busybox官网 下载Busybox的压缩包。

这里我下载的是 busybox-1.31.1.tar.bz2

解压到合适的位置

1
tar -jxvf busybox-1.31.1.tar.bz2 -C ~/c-workspace/

编译Busybox

Busybox 的编译方式和内核相似。

首先要使用 make menuconfig 配置编译选项。这里建议将 Busybox 改为静态编译。

1
2
3
4
5
6
7
8
make menuconfig
# menuconfig begin
Settings -->
[*] Build static binary (no shared libs)
# menuconfig end

make CORSS_COMPILE=arm-linux-gnueabi-
make install

Busybox 默认会安装到 ./_install 目录下

1
2
dhd@dhd-pc:~/c-workspace/busybox-1.31.1/_install$ ls
bin linuxrc sbin usr

构建最小根文件系统

_install 目录拷贝一份出来,用于制作根文件系统。

1
2
mkdir -p ~/qemu ; cp _install/ ~/qemu/rootfs/ -rf
cd ~/qemu/rootfs/

创建init文件

1
2
rm linuxrc
ln -s bin/busybox init

创建控制台设备文件

1
2
mkdir dev
sudo mknod -m 600 dev/console c 5 1

注意是 dev/console 而不是 /dev/console

创建配置文件目录及文件

1
2
mkdir etc
touch etc/inittab

inittab 的内容如下

1
2
3
4
5
6
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

创建初始化脚本

1
2
3
mkdir init.d
touch etc/init.d/rcS
chmod +x etc/init.d/rcS

初始化脚本 rcS 的内容为

1
2
3
4
#!/bin/sh
export PATH=/sbin:/bin:/usr/bin;/usr/sbin;
export HOSTNAME=dhd
echo "dhd minisystem start..."

制作最小根文件系统镜像

1
find . | cpio -o -H newc | gzip > ../rootfs.img

测试

把 qemu 内核和文件系统的命令放到 arm_start.sh 文件中。

1
2
3
4
5
6
7
qemu-system-arm \
-M vexpress-a9 \
-m 1024M \
-kernel /home/dhd/kernel/linux-5.5.6/arch/arm/boot/zImage \
-dtb /home/dhd/kernel/linux-5.5.6/arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
-initrd /home/dhd/qemu/rootfs.img \
-nographic

执行 arm_start.sh 启动内核并挂载根文件系统。

result