4. 常见嵌入式文件系统类型
在嵌入式 Linux 系统中,根文件系统(rootfs)并不是“随便选一个能挂载的格式”即可。不同存储介质(NOR/NAND/eMMC/SD/DRAM)、不同读写需求(只读、频繁写、掉电保护)、不同启动阶段(initramfs 先起、再切到真实 rootfs)都会直接影响文件系统选型。本节把常见类型放在同一张“介质—特性—场景”坐标系里对比,帮助你建立可落地的选型依据。
一、核心原理:先看介质,再看读写模型
嵌入式文件系统大致分为三类:块设备型(ext4、squashfs、initramfs/tmpfs 在内存中)、裸 NAND/NOR 型(jffs2、ubifs、yaffs2)。块设备型依赖通用块层与页缓存,适合 eMMC/SD/UFS;裸闪存型直接管理擦除块、坏块与磨损均衡,适合 SPI NOR 与 NAND。
关键差异在于:是否支持原地写、是否有日志/日志结构、是否压缩、是否可写、是否依赖 MTD 子系统。例如 squashfs 是只读压缩文件系统,适合固化 rootfs;ubifs 是 NAND 上的日志结构文件系统,支持压缩与掉电一致性;tmpfs 完全驻留内存,掉电即失,适合 /tmp、/run 等临时目录。
二、方法流程:从需求到选型的四步判断
- 确定介质类型:eMMC/SD 走块设备路线,优先 ext4;SPI NOR/NAND 走 MTD 路线,优先 jffs2/ubifs/yaffs2。
- 确定读写属性:只读固件用 squashfs;需要频繁写且要求掉电一致性,用 ubifs 或 ext4(带 journal)。
- 确定容量与压缩需求:容量紧张时 squashfs/ubifs 的压缩能显著节省空间;ext4 不压缩。
- 确定启动阶段:内核早期需要先挂一个最小根,用 initramfs;随后 switch_root 到真实 rootfs。
三、案例/场景:典型组合与命令
场景 A:i.MX6 + eMMC,系统分区只读、数据分区可写。常见做法是 rootfs 用 squashfs 或 ext4,数据分区用 ext4。挂载示例:
# 只读挂载 squashfs 根
mount -t squashfs -o ro /dev/mmcblk0p2 /mnt/rootfs
# 可写数据分区
mount -t ext4 -o rw,noatime /dev/mmcblk0p3 /data
# 查看当前文件系统类型
df -T
cat /proc/mounts
场景 B:SPI NAND 上保存配置与日志。使用 ubifs 前需先做 UBI 镜像:
mkfs.ubifs -r rootfs -m 2048 -e 126976 -c 2048 -o rootfs.ubifs
ubinize -o rootfs.ubi -m 2048 -p 128KiB ubinize.cfg
# ubinize.cfg 中 volume 类型可设为 static 或 dynamic
场景 C:initramfs 作为早期根,负责加载驱动并挂载真实 rootfs:
# 内核配置
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE="initramfs.cpio.gz"
# 启动后 switch_root
switch_root /newroot /sbin/init
四、对比清单与误区复盘
| 类型 | 介质 | 可写 | 压缩 | 掉电一致性 | 典型用途 |
|---|---|---|---|---|---|
| ext4 | eMMC/SD | 是 | 否 | 日志,较好 | 通用根/数据分区 |
| squashfs | 块设备/MTD | 否 | 是 | 只读,天然安全 | 只读固件 rootfs |
| jffs2 | NOR/NAND | 是 | 是 | 日志结构,较好 | 小容量 NOR 配置区 |
| ubifs | NAND | 是 | 是 | 日志结构 + UBI,好 | NAND 可写分区 |
| yaffs2 | NAND | 是 | 否 | 日志结构,较好 | 老 NAND 平台 |
| initramfs | DRAM | 是(内存) | 是(cpio 压缩) | 掉电即失 | 早期启动、救援 |
| tmpfs | DRAM | 是 | 否 | 掉电即失 | /tmp、/run、/dev/shm |
复盘时建议按“介质 → 读写 → 容量 → 启动阶段”四步重新核对:如果 rootfs 只读且要省空间,squashfs 往往优于 ext4;如果数据分区需要频繁写且介质是 NAND,ubifs 比 jffs2 更合适;如果只是临时文件,tmpfs 最轻量。选型没有绝对最优,只有与硬件、启动流程和可靠性目标最匹配的组合。