2026-09-23 08:10:18 +00:00
2026-09-23 08:09:28 +00:00
2026-09-23 08:10:18 +00:00

Linux 内核 + BusyBox 最小系统构建指南

基于 Linux 6.12 + BusyBox,使用 QEMU 启动的最小根文件系统。 本文档记录从零构建到成功进入 shell 的完整过程,包含故障排查。


环境准备

sudo apt update
sudo apt install -y build-essential libncurses-dev bison flex \
  libssl-dev libelf-dev git bc rsync cpio gzip wget gcc-14 qemu-system-x86

目录结构:

/home/zmn/
├── linux-6.12/          # 内核源码
├── busybox/             # BusyBox 源码
├── rootfs/              # 根文件系统
└── initramfs.cpio.gz    # 打包后的 initramfs

第一步:下载并解压内核源码

cd /home/zmn
wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v6.x/linux-6.12.tar.xz
tar -xf linux-6.12.tar.xz

第二步:配置内核

cd /home/zmn/linux-6.12
make x86_64_defconfig

关键配置项

x86_64_defconfig 已默认启用以下必需选项(可用 grep 验证):

配置项 作用
CONFIG_SERIAL_8250=y 串口驱动
CONFIG_SERIAL_8250_CONSOLE=y 串口控制台(console=ttyS0 依赖此项)
CONFIG_BLK_DEV_INITRD=y initramfs 支持(-initrd 依赖此项)
CONFIG_RD_GZIP=y gzip 压缩的 initrd 解压支持
CONFIG_DEVTMPFS=y /dev 自动挂载
CONFIG_PRINTK=y 内核日志输出

验证:

grep -E 'CONFIG_(SERIAL_8250_CONSOLE|BLK_DEV_INITRD|RD_GZIP|DEVTMPFS|PRINTK)=' .config

注意:不要用 make tinyconfig,它几乎关闭所有驱动,导致没有串口控制台输出, QEMU 只会显示一个闪烁的光标。


第三步:编译内核

cd /home/zmn/linux-6.12
make CC=gcc-14 -j$(nproc)

编译成功标志:

Kernel: arch/x86/boot/bzImage is ready  (#1)

验证产物:

ls -la arch/x86/boot/bzImage
# 应输出类似:-rw-r--r-- 1 zmn zmn 13583360 ... bzImage

第四步:下载并配置 BusyBox

cd /home/zmn
git clone --depth 1 https://git.busybox.net/busybox
cd busybox
make defconfig

关键配置:静态编译

# 开启静态链接(不依赖 libc.so 等共享库)
sed -i 's/^# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config

# 禁用 tc(新版内核头文件已删除 CBQ 结构体,会导致编译失败)
sed -i 's/^CONFIG_TC=y/# CONFIG_TC is not set/' .config

grep -E '^CONFIG_STATIC=|^CONFIG_TC=' .config
# 应输出:
# CONFIG_STATIC=y
# # CONFIG_TC is not set

为什么必须静态编译:initramfs 中没有 /lib、/lib64, 动态链接的 BusyBox 在启动时会因找不到 ld-linux-x86-64.so.2 而失败, 内核 panic,屏幕上什么都看不到。

为什么必须禁用 tc:make defconfig 默认开启 CONFIG_TC=y, 但 networking/tc.c 引用的 TCA_CBQ_* 等结构体已在新版内核头文件中删除, 会导致编译报错 TCA_CBQ_MAX undeclared。


第五步:编译 BusyBox

cd /home/zmn/busybox
make CC=gcc-14 -j$(nproc)

编译成功后验证:

file busybox
# 应输出:ELF 64-bit LSB executable, x86-64, ... statically linked

第六步:构建根文件系统

6.1 创建目录结构

mkdir -p /home/zmn/rootfs/{bin,sbin,etc,proc,sys,dev,tmp,root,usr/bin,usr/sbin}

6.2 安装 BusyBox

cd /home/zmn/busybox
make CONFIG_PREFIX=/home/zmn/rootfs install

验证:

file /home/zmn/rootfs/bin/busybox
# 应输出:statically linked

6.3 编写 init 脚本

用 cat 写入 /home/zmn/rootfs/init:

cat > /home/zmn/rootfs/init << 'EOF'
#!/bin/sh

mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev

hostname minimal-linux
exec /bin/sh
EOF

赋予执行权限:

chmod +x /home/zmn/rootfs/init

验证:

ls -la /home/zmn/rootfs/init
# 应输出:-rwxr-xr-x ... /home/zmn/rootfs/init

6.4 init 脚本说明

命令 作用
mount -t proc 挂载进程信息系统,ps、/proc 依赖它
mount -t sysfs 挂载 sysfs,/sys 依赖它
mount -t devtmpfs 挂载设备文件系统,自动创建 /dev/ttyS0 等设备节点
exec /bin/sh 用 shell 替换当前进程,进入交互式命令行

第七步:打包 initramfs

cd /home/zmn/rootfs
find . | cpio -o -H newc 2>/dev/null | gzip > /home/zmn/initramfs.cpio.gz

验证:

ls -la /home/zmn/initramfs.cpio.gz
zcat /home/zmn/initramfs.cpio.gz | cpio -t 2>/dev/null | grep '^init$'
# 应输出:init

第八步:QEMU 启动

qemu-system-x86_64 \
  -kernel /home/zmn/linux-6.12/arch/x86/boot/bzImage \
  -initrd /home/zmn/initramfs.cpio.gz \
  -append "console=ttyS0 rdinit=/init" \
  -nographic \
  -m 256M

参数说明

参数 作用
-kernel 指定内核 bzImage 路径
-initrd 指定 initramfs 路径
console=ttyS0 内核日志输出到串口(配合 -nographic 显示在终端)
rdinit=/init 指定 initramfs 中的初始进程为 /init
-nographic 不使用图形窗口,串口重定向到当前终端
-m 256M 分配 256MB 内存

启动成功标志

滚动的内核日志结束后出现:

Run /init as init process
/bin/sh: can't access tty; job control turned off
~ #

~ # 即为 shell 提示符,此时可以输入命令:

~ # uname -r
6.12.0
~ # ls
bin      etc      linuxrc  root     sys      usr
dev      init     proc     sbin     tmp

退出 QEMU

  • 方法一:shell 中输入 poweroff
  • 方法二:按 Ctrl+A 再按 X

故障排查

症状:只有一个闪烁的光标,其他什么都没有

按以下顺序排查:

序号 检查项 排查命令 修复方法
1 bzImage 是否存在 ls -la arch/x86/boot/bzImage 重新编译内核
2 是否启用了串口控制台 grep SERIAL_8250_CONSOLE .config 改用 x86_64_defconfig
3 是否启用了 initrd 支持 grep BLK_DEV_INITRD .config 改用 x86_64_defconfig
4 BusyBox 是否静态链接 file rootfs/bin/busybox 开启 CONFIG_STATIC=y 重编
5 init 是否存在且可执行 ls -la rootfs/init chmod +x rootfs/init
6 initramfs 是否包含 init zcat initramfs.cpio.gz | cpio -t | grep init 重新打包

常见错误对照

错误信息 原因 解决
qemu: could not open kernel file bzImage 不存在 编译内核
Run /init as init process 后无输出 init 不可执行或 BusyBox 动态链接缺库 检查权限、改静态编译
tc.c: error: 'TCA_CBQ_MAX' undeclared CONFIG_TC=y 但内核已删除 CBQ 结构体 禁用 CONFIG_TC 后重编
busybox: cannot open ... No such file or directory 上次编译失败,二进制未生成 修复编译错误后重新 make
can't access tty; job control turned off 正常现象,无需处理 忽略
内核 panic No working init found initramfs 未加载或 init 路径错误 检查 rdinit= 和 BLK_DEV_INITRD
终端完全没有内核日志 缺少串口控制台支持 检查 SERIAL_8250_CONSOLE

完整构建脚本

将以下内容保存为 build.sh,可一键完成整个构建流程:

#!/bin/bash
set -e

KERNEL_DIR=/home/zmn/linux-6.12
BB_DIR=/home/zmn/busybox
ROOTFS=/home/zmn/rootfs
INITRAMFS=/home/zmn/initramfs.cpio.gz

echo "=== [1/6] 配置内核 ==="
cd "$KERNEL_DIR"
make x86_64_defconfig

echo "=== [2/6] 编译内核 ==="
make CC=gcc-14 -j"$(nproc)"
test -f arch/x86/boot/bzImage && echo "bzImage OK"

echo "=== [3/6] 配置 BusyBox(静态编译,禁用 tc)==="
cd "$BB_DIR"
make defconfig
sed -i 's/^# CONFIG_STATIC is not set/CONFIG_STATIC=y/' .config
sed -i 's/^CONFIG_TC=y/# CONFIG_TC is not set/' .config
grep -E '^CONFIG_STATIC=|^CONFIG_TC=' .config

echo "=== [4/6] 编译 BusyBox ==="
make CC=gcc-14 -j"$(nproc)"
file busybox | grep -q "statically linked" && echo "static OK"

echo "=== [5/6] 安装到 rootfs 并写 init ==="
mkdir -p "$ROOTFS"/{bin,sbin,etc,proc,sys,dev,tmp,root,usr/bin,usr/sbin}
make CONFIG_PREFIX="$ROOTFS" install
cat > "$ROOTFS/init" << 'INITEOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
hostname minimal-linux
exec /bin/sh
INITEOF
chmod +x "$ROOTFS/init"

echo "=== [6/6] 打包 initramfs ==="
cd "$ROOTFS"
find . | cpio -o -H newc 2>/dev/null | gzip > "$INITRAMFS"
echo "Done: $INITRAMFS"

echo ""
echo "启动命令:"
echo "qemu-system-x86_64 -kernel $KERNEL_DIR/arch/x86/boot/bzImage -initrd $INITRAMFS -append \"console=ttyS0 rdinit=/init\" -nographic -m 256M"

运行:

chmod +x build.sh
./build.sh
S
Description
最小Linux系统编译
Readme MIT
42 KiB
0 Stars 1 Watchers 0 Forks