根文件系统(rootfs)
一、根文件系统的内容
/
├── bin/ 基本命令
├── sbin/ 系统命令
├── etc/ 配置
├── dev/ 设备文件(devtmpfs)
├── proc/ 进程信息(procfs)
├── sys/ 内核对象(sysfs)
├── lib/ 库
├── usr/ 用户程序
├── var/ 变化的数据
├── tmp/ 临时
├── root/ root 家目录
├── home/ 用户家目录
├── boot/ 启动文件(独立分区)
├── mnt/, /media 挂载点
├── opt/ 第三方
└── run/ 运行时数据(tmpfs)
二、根文件系统的挂载
内核
↓
挂载第一个文件系统(initramfs 或 rootfs)
↓
执行 /sbin/init
↓
init 继续挂载 /proc /sys /dev ...
↓
启动服务
三、initramfs / initrd
1. 概念
- 内核自带的"临时 rootfs"
- 在挂载真正的 rootfs 之前提供环境
- 解压到 tmpfs(基于 RAM)
2. 用途
- 加载驱动才能访问真 rootfs(如 USB 存储根)
- 加密根
- 工厂恢复模式
- 极简启动
3. 内核配置
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="..." # 可指定 cpio 文件
4. 制作
# 准备目录
mkdir -p initramfs/{bin,sbin,etc,proc,sys,dev}
cd initramfs
# ... 填充内容
# 打包
find . | cpio -o -H newc | gzip > ../initramfs.cpio.gz
# 或
find . | cpio -o -H newc > ../initramfs.cpio
5. 内容示例
initramfs/
├── init # 可执行脚本
├── bin/
│ └── busybox -> /bin/busybox
├── dev/
│ └── console
└── lib/
init 脚本:
#!/bin/sh
mount -t proc proc /proc
mount -t sysfs sys /sys
mount -t devtmpfs dev /dev
# 加载驱动
modprobe usb_storage
sleep 2
# 挂载真根
mount -t ext4 /dev/sda1 /mnt
exec switch_root /mnt /sbin/init
四、真实 rootfs 构建(手动)
1. 创建基础目录
ROOTFS=/path/to/rootfs
mkdir -p $ROOTFS/{bin,sbin,etc,dev,proc,sys,run,tmp,usr/{bin,sbin,lib},var,lib,home,root}
2. 编译 / 安装 BusyBox
make CONFIG_PREFIX=$ROOTFS install
3. 创建设备文件(可选,devtmpfs 会自动创建)
sudo mknod $ROOTFS/dev/console c 5 1
sudo mknod $ROOTFS/dev/null c 1 3
sudo mknod $ROOTFS/dev/tty c 5 0
sudo chmod 600 $ROOTFS/dev/console
4. 准备 etc
cat > $ROOTFS/etc/fstab <<EOF
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devtmpfs /dev devtmpfs mode=0755,nosuid 0 0
tmpfs /tmp tmpfs mode=1777 0 0
tmpfs /run tmpfs mode=0755,nosuid,nodev 0 0
EOF
cat > $ROOTFS/etc/passwd <<EOF
root:x:0:0:root:/root:/bin/sh
EOF
cat > $ROOTFS/etc/group <<EOF
root:x:0:
EOF
cat > $ROOTFS/etc/hostname <<EOF
myboard
EOF
cat > $ROOTFS/etc/inittab <<EOF
::sysinit:/etc/init.d/rcS
::respawn:/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/etc/init.d/rcK
EOF
mkdir -p $ROOTFS/etc/init.d
cat > $ROOTFS/etc/init.d/rcS <<EOF
#!/bin/sh
mount -a
echo "Welcome to MyBoard!"
EOF
chmod +x $ROOTFS/etc/init.d/rcS
5. 打包成镜像
# ext4 镜像
dd if=/dev/zero of=rootfs.ext4 bs=1M count=64
mkfs.ext4 -F -L rootfs rootfs.ext4
sudo mount rootfs.ext4 /mnt
sudo cp -a $ROOTFS/* /mnt/
sudo umount /mnt
# squashfs(只读、压缩)
mksquashfs $ROOTFS rootfs.squashfs -comp xz -noappend
# initramfs
find $ROOTFS | cpio -o -H newc | gzip > rootfs.cpio.gz
五、devtmpfs
# 内核配置
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
内核自动挂载 /dev,无需 mknod。
六、OverlayFS(OTA 关键)
mount -t overlay overlay -o lowerdir=/mnt/ro,upperdir=/mnt/rw,workdir=/mnt/work /mnt/merged
应用:
- Docker 镜像分层
- 嵌入式 OTA:A/B 分区
- 只读根文件系统 + 可写 overlay
七、其他文件系统
1. tmpfs(内存)
- /tmp、/run 默认
- 适合临时文件
- 重启丢失
2. squashfs(压缩只读)
- 极小占用
- 适合只读 rootfs
3. ubifs / jffs2(NAND)
- 见
04-kernel-driver/10-block-device.md
4. f2fs(eMMC)
- 闪存优化
- 适合可写 rootfs
八、嵌入式 rootfs 选择
| 场景 | 推荐 |
|---|---|
| 开发调试 | initramfs + NFS root |
| NAND 启动 | jffs2 / ubifs |
| eMMC 启动 | ext4 |
| 量产只读 | squashfs + overlay |
| OTA | A/B 分区 |
九、NFS Root(开发神器)
# U-Boot 环境变量
nfsroot=192.168.1.10:/path/to/rootfs
ip=dhcp
setenv bootargs root=/dev/nfs nfsroot=${nfsroot} ip=${ip}
- 主机编辑文件直接生效
- 不需要每次烧录
- 调试极方便