嵌入式 Linux 根文件系统制作与移植
1. 前言
1.1 为什么需要根文件系统?
在嵌入式Linux系统中,内核(Kernel)负责硬件驱动和资源调度,而根文件系统(Root Filesystem, RootFS)则是用户空间的"地基"。它包含系统启动必需的 init 进程、Shell 命令、动态链接库、配置文件和应用程序。没有根文件系统,内核即使启动成功也会在最后一步因为 "No init found" 而崩溃。
工业级开发常见两类需求:
- 极致轻量(BusyBox):用于 Flash 空间极小(<64MB)设备,或 Recovery/维护系统。
- 全功能集成(Buildroot/Yocto):用于智能网关/HMI 等,需要 Qt、Python、OpenCV 等复杂库。
本文以 迅为电子 RK3568(ARMv8,Cortex-A55)为例,讲解 BusyBox 与 Buildroot 两种方案 。
1.2 核心工具对比

| 工具 | 核心定位 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|---|
| BusyBox | 极简工具集 | 体积极小、启动快、完全可控 | 依赖库/配置需手动处理 | 极简系统、维护系统、教学 |
| Buildroot | 自动化构建系统 | 一键生成(工具链+RootFS+可选内核)、易管理第三方库 | 编译时间长、初次配置复杂 | 产品级开发、快速原型验证 |
2. 基础准备
2.1 硬件与环境
-
开发板:迅为 RK3568(eMMC/SD 卡启动,2GB RAM)
-
主机环境:Ubuntu 20.04/22.04 LTS(64位)
-
交叉编译工具链 :
aarch64-linux-gnu-gcc(ARMv8 64位)- 注意:尽量确保工具链版本与内核/BSP 配套,否则可能出现 ABI 或库不匹配问题
-
调试工具:USB 转串口模块
-
提示 :RK3568 常见默认串口波特率 1,500,000 (1.5M)。请确认 CH340/CP2102 等芯片与驱动支持该波特率,否则会乱码。
2.2 RK3568 启动流程简述
U-Boot 通过 bootargs 告诉内核 rootfs 在哪(如 root=/dev/mmcblk0p2 或 root=/dev/nfs)。

3. 方案一:BusyBox 制作极简根文件系统
3.1 获取并配置 BusyBox
(1)下载源码
bash
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar -jxvf busybox-1.36.1.tar.bz2
cd busybox-1.36.1
(2)配置(menuconfig)
bash
make defconfig
make menuconfig
关键配置(针对 RK3568):
Settings→Build static binary (no shared libs):不勾选(动态库利于扩展;极致极简可选静态减少库管理)Settings→Cross compiler prefix:aarch64-linux-gnu-Settings→Destination path for 'make install':./_installSettings→vi-style line editing commands:建议勾选(历史、编辑更方便)Linux System Utilities→ 勾选mdev(配合热插拔;基础节点由 devtmpfs 提供)
3.2 编译与安装
bash
make -j$(nproc)
make install
3.3 构建 RootFS 骨架(关键步骤)

(1)创建目录结构
bash
cd _install
mkdir -p dev etc/init.d lib lib64 home mnt proc root sys tmp var usr/lib usr/bin
AArch64 经常出现
/lib+/lib64并存的情况,建议两者都准备。
(2)最小设备节点
在 devtmpfs 之前,这两个节点能避免很多早期启动问题:
bash
sudo mknod -m 600 dev/console c 5 1
sudo mknod -m 666 dev/null c 1 3
3.4 完善配置文件
A. etc/inittab
text
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
respawn适合调试:shell 退出会自动重启。产品化可改为askfirst或启动你的主程序。
B. etc/init.d/rcS(启动脚本:现代化 devtmpfs + mdev 热插拔)
sh
#!/bin/sh
# 挂载虚拟文件系统
mount -t proc proc /proc
mount -t sysfs sysfs /sys
# /tmp:很多程序依赖可写临时目录
mount -t tmpfs tmpfs /tmp
chmod 1777 /tmp
# 关键:devtmpfs(内核自动填充 /dev 设备节点)
# 注意:需要内核启用 CONFIG_DEVTMPFS / CONFIG_DEVTMPFS_MOUNT
mount -t devtmpfs none /dev
# mdev:用于处理热插拔(U盘/网卡热插拔等)
# 说明:hotplug 的行为与内核配置有关(部分内核可能禁用 uevent helper)
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
# 网络配置(示例:eth0)
ifconfig lo 127.0.0.1 up
# 方案1:固定 IP(工业现场常用)
ifconfig eth0 192.168.1.101 netmask 255.255.255.0 up
route add default gw 192.168.1.1 2>/dev/null
# 方案2:DHCP(调试更方便,需 BusyBox 启用 udhcpc)
# udhcpc -i eth0 &
echo "System initialized using BusyBox..."
赋予执行权限:
bash
chmod +x etc/init.d/rcS
C. etc/fstab
text
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
D. 用户与组配置(避免 I have no name!)
etc/passwd:
text
root:x:0:0:root:/root:/bin/sh
etc/group:
text
root:x:0:
(可选)etc/profile:
sh
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
3.5 移植动态链接库
很多人遇到过这种现象:
- 文件明明存在,但运行报:
No such file or directory
这通常不是文件缺失,而是动态链接器(loader)缺失或路径不对。
(1)确认 BusyBox 需要的解释器路径
在宿主机执行:
bash
aarch64-linux-gnu-readelf -l _install/bin/busybox | grep "interpreter"
常见输出之一:
/lib/ld-linux-aarch64.so.1- 或
/lib64/ld-linux-aarch64.so.1
记住它在哪个目录(lib / lib64),后面要对齐拷贝。
(2)从 sysroot 拷贝库(按目录对齐)
bash
SYSROOT=$(aarch64-linux-gnu-gcc -print-sysroot)
echo "$SYSROOT"
推荐做法:同时准备 lib 与 lib64
bash
# 关键:把 loader 拷对目录(lib 或 lib64)
cp -av "$SYSROOT/lib/ld-linux-aarch64.so.1" lib/ 2>/dev/null || true
cp -av "$SYSROOT/lib64/ld-linux-aarch64.so.1" lib64/ 2>/dev/null || true
# 拷贝常用运行库(根据 sysroot 实际情况,lib/lib64/usr/lib 可能存在其一或多个)
cp -av "$SYSROOT/lib/"*.so* lib/ 2>/dev/null || true
cp -av "$SYSROOT/lib64/"*.so* lib64/ 2>/dev/null || true
cp -av "$SYSROOT/usr/lib/"*.so* usr/lib/ 2>/dev/null || true
(3)剥离符号(可选,大幅减体积)
bash
aarch64-linux-gnu-strip lib/*.so* 2>/dev/null || true
aarch64-linux-gnu-strip lib64/*.so* 2>/dev/null || true
aarch64-linux-gnu-strip usr/lib/*.so* 2>/dev/null || true
(4)检查点
bash
ls -l lib/ld-linux-aarch64.so.1 2>/dev/null || true
ls -l lib64/ld-linux-aarch64.so.1 2>/dev/null || true
只要解释器与库齐了,BusyBox 基本就能跑。
3.6 制作 ext4 镜像与打包(确保属主为 root)
⚠️ 为保证文件属主/权限正确,打包时务必使用
sudo。
bash
# 1) 制作空镜像(示例 128MB,按 du -sh 估算后留余量)
dd if=/dev/zero of=rootfs.ext4 bs=1M count=128
mkfs.ext4 -F rootfs.ext4
# 2) 挂载(关键:用 loop)
mkdir -p /mnt/tmp_rootfs
sudo mount -o loop rootfs.ext4 /mnt/tmp_rootfs
# 3) 拷贝(保留属性)
sudo cp -a _install/* /mnt/tmp_rootfs/
sync
# 4) 卸载
sudo umount /mnt/tmp_rootfs
4. 方案二:Buildroot 自动化构建(推荐)
Buildroot 适合需要集成 SSH、Python、Qt 等复杂功能场景。
4.1 快速配置
注意:Buildroot 不同版本 defconfig 名称可能不同。若找不到 RK3568 专用配置,优先使用
rockchip64_defconfig。
bash
make rockchip64_defconfig
make menuconfig
必选建议:
System configuration→Root password:设置 root 密码(否则 SSH 登录不方便)Target packages→Networking applications:勾选dropbear(轻量)或opensshTarget packages→Editors:勾选vim/nanoFilesystem images:确保勾选ext2/3/4 root filesystem并选择ext4
4.2 国内下载慢的解决办法
Build options→Mirrors and Download locations:配置镜像源- 或提前把源码包放入
dl/目录
4.3 编译
bash
make -j$(nproc)
# 输出通常在 output/images/rootfs.ext4
5. 开发调试技巧
5.1 NFS 网络根文件系统(开发效率加速器)

主机端(Ubuntu)
bash
sudo apt-get install -y nfs-kernel-server
sudo mkdir -p /home/nvdia/rootfs_nfs
编辑 /etc/exports:
text
/home/nvdia/rootfs_nfs *(rw,sync,no_root_squash,no_subtree_check)
重启服务:
bash
sudo service nfs-kernel-server restart
开发板端(U-Boot)设置 bootargs
bash
setenv bootargs "console=ttyS2,1500000 root=/dev/nfs nfsroot=192.168.1.100:/home/nvdia/rootfs_nfs,v3,tcp rw ip=192.168.1.101:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc"
saveenv
boot
优势:在 Ubuntu 上编译完程序直接复制到 NFS 目录,板端立即运行,不用频繁烧录。
5.2 开启 SSH
简要流程:
- 交叉编译 dropbear 并放入 rootfs
- 板端生成 key:
bash
mkdir -p /etc/dropbear
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
- 启动:
bash
dropbear
6. 常见故障排查
- Kernel panic - not syncing: No init found
- 检查
bootargs的init=是否正确(/linuxrcvs/sbin/init) - 检查
linuxrc/busybox是否可执行 - 最常见原因 :动态库不全或 loader 缺失(
ld-linux-aarch64.so.1)
- I have no name!@rk3568:/#
- 缺少
/etc/passwd与/etc/group
- 服务提示 Permission denied
- 打包没用
sudo,属主不对 - 修复:
sudo chown -R root:root _install后重新打包
- 串口乱码
- 再次确认波特率是否为 1500000,以及 USB 转串口芯片/驱动是否支持
7. 总结
- 方案选择
- 极致轻量、深度定制:BusyBox
- 快速集成、标准化构建:Buildroot
- RK3568 移植核心要点
- bootargs 必须正确:
console=、root=、rootfstype=、(建议)rootwait /proc/sys/tmp挂载正确- 动态库必须匹配工具链,并确保动态链接器存在(AArch64 常见
ld-linux-aarch64.so.1) - 建议准备
/dev/console/dev/null"保命节点"
核心宗旨:根据硬件资源、项目需求、开发周期,在"体积 / 功能 / 开发效率"间找到平衡。
参考资料
- BusyBox:busybox.net
- Buildroot:buildroot.org/docs.html
- 迅为电子 RK3568 开发手册(厂商资料)