嵌入式存储文件系统:ext4、jffs2、ubifs 格式选型与适配
选文件系统就像选鞋子——跑步穿跑鞋,登山穿登山靴。把 ext4 硬塞进 NOR Flash,就像穿高跟鞋踢足球,不是不行,是疼。
引言
嵌入式设备的存储介质种类繁多:SD 卡、eMMC、NOR Flash、NAND Flash……每种介质的特性不同,对应的文件系统也不同。选错文件系统,轻则性能拉胯,重则数据丢失。本文将对比主流嵌入式文件系统格式,给出选型建议和适配方法。
一、嵌入式存储介质分类
在选文件系统之前,先搞清楚存储介质的类型:
| 介质类型 | 特点 | 典型容量 | 常见用途 |
|---|---|---|---|
| NOR Flash | 读取快、随机访问、XIP可执行 | 1~32MB | 存放Bootloader、内核 |
| NAND Flash | 密度高、便宜、有坏块 | 128MB~4GB | 存放根文件系统、用户数据 |
| eMMC | 内置控制器、无坏块问题 | 4~64GB | 手机、平板、开发板 |
| SD/TF卡 | 可插拔、便携 | 4~128GB | 开发板、便携设备 |
| SPI Flash | 接口简单、容量小 | 4~32MB | 小型IoT设备 |
关键区别:NOR/NAND Flash 是裸芯片,需要文件系统处理坏块和磨损均衡;eMMC/SD 卡内置了 FTL(Flash Translation Layer)控制器,对上层透明。
二、主流文件系统格式对比
2.1 全面对比表
| 特性 | ext4 | JFFS2 | UBIFS | SquashFS | YAFFS2 |
|---|---|---|---|---|---|
| 支持介质 | eMMC/SD | NOR/NAND | NAND | 任意 | NAND |
| 可写性 | 读写 | 读写 | 读写 | 只读 | 读写 |
| 掉电安全 | 否(需journal) | 是 | 是 | N/A | 是 |
| 磨损均衡 | 不需要(FTL处理) | 内置 | UBI层处理 | 不需要 | 内置 |
| 坏块管理 | 不需要(FTL处理) | 内置 | UBI层处理 | 不需要 | 内置 |
| 压缩 | 否 | 是(zlib) | 是(lzo/zlib) | 是(xz/gzip) | 否 |
| 挂载速度 | 快 | 慢(全扫描) | 快(索引) | 快 | 中 |
| 内存占用 | 低 | 高(全加载) | 中 | 低 | 中 |
| 适用容量 | 任意 | <128MB | <2GB | 任意 | <2GB |
2.2 各格式详解
ext4
桌面 Linux 的主力文件系统。在嵌入式中主要用于eMMC 和 SD 卡。
- 优点:成熟稳定、性能好、工具链完善
- 缺点:不支持掉电安全(虽然有 journal,但嵌入式突然断电仍有风险)
- 适用:eMMC、SD 卡,资源相对充足的设备
JFFS2
专为 Flash 设计的日志结构文件系统。
- 优点:掉电安全、支持压缩、支持 NOR 和 NAND
- 缺点:挂载速度随容量线性增长(128MB 需要 10+ 秒),内存占用大
- 适用:小容量 NOR Flash(<32MB),小容量 NAND
UBIFS
JFFS2 的继任者,基于 UBI 子系统,专为大容量 NAND Flash 优化。
- 优点:挂载快(维护索引树)、支持压缩、掉电安全
- 缺点:配置复杂(需要先创建 UBI 卷)
- 适用:大容量 NAND Flash(128MB~2GB)
SquashFS
只读压缩文件系统,适合存放不需要修改的系统文件。
- 优点:压缩率高(xz压缩可节省60%+空间)、挂载快
- 缺点:只读,无法修改
- 适用:根文件系统的只读部分、overlayfs 的底层
三、选型决策流程
存储介质是什么? │ ┌────────────┼────────────┐ │ │ │ eMMC/SD NAND Flash NOR Flash │ │ │ ext4(首选) 容量>128MB? 容量<32MB? │ / \ / \ 否 是 否 是 否 │ │ │ │ │ SquashFS UBIFS JFFS2 JFFS2 SquashFS (只读层) (只读层)选型原则总结
- eMMC/SD 卡→ ext4(读写)或 squashfs(只读)
- 大容量 NAND→ UBIFS
- 小容量 NAND→ JFFS2
- NOR Flash→ JFFS2(小容量)或 SquashFS(只读)
- 需要只读保护→ SquashFS + OverlayFS(上层可写)
四、各文件系统适配方法
4.1 ext4 适配
# 1. 创建 ext4 镜像ddif=/dev/zeroof=rootfs.ext4bs=1Mcount=256mkfs.ext4-Lrootfs rootfs.ext4# 2. 挂载并填充内容mkdir-p/mnt/rootfssudomount-oloop rootfs.ext4 /mnt/rootfssudocp-a_install/* /mnt/rootfs/sudoumount/mnt/rootfs# 3. 烧录到 SD 卡分区sudoddif=rootfs.ext4of=/dev/sdb2bs=1M内核 bootargs 配置:
root=/dev/mmcblk0p2rootfstype=ext4 rootwait rw4.2 JFFS2 适配
JFFS2 镜像使用mkfs.jffs2工具制作:
# 1. 安装 mtd-utilssudoaptinstallmtd-utils# 2. 制作 JFFS2 镜像# -p 0x1000000: 镜像大小16MB# -r rootfs/: 源目录# -o rootfs.jffs2: 输出文件# --pad: 填充到指定大小mkfs.jffs2\-s0x800\-e0x20000\-p0x1000000\-drootfs/\-orootfs.jffs2# 参数说明:# -s: 页大小(NAND页大小,2048字节=0x800)# -e: 擦除块大小(128KB=0x20000)# -p: 填充到指定大小# -d: 源目录# -o: 输出文件内核 bootargs 配置:
root=/dev/mtdblock2rootfstype=jffs2 rw4.3 UBIFS 适配
UBIFS 的制作流程比 JFFS2 复杂,需要两步:先制作 UBIFS 镜像,再封装为 UBI 镜像。
# 1. 制作 UBIFS 镜像# -m 2048: 最小IO大小(NAND页大小)# -e 129024: 擦除块大小(128KB减去UBI头开销)# -c 2048: 最大逻辑擦除块数# -r rootfs/: 源目录mkfs.ubifs\-m2048\-e129024\-c2048\-rrootfs/\-orootfs.ubifs# 2. 封装为 UBI 镜像# 需要创建 ubifs.ini 配置文件cat>ubifs.ini<<'EOF' [ubifs] mode=ubi image=rootfs.ubifs vol_id=0 vol_size=256MiB vol_type=dynamic vol_name=rootfs vol_alignment=1 vol_flags=autoresize EOF# 生成 UBI 镜像ubinize\-m2048\-p128KiB\-s2048\-O2048\-orootfs.ubi\ubifs.ini关键参数计算:
| 参数 | 含义 | 计算方式 |
|---|---|---|
-m | 最小IO大小 | = NAND 页大小 |
-e | 逻辑擦除块大小 | = 物理擦除块 - 2×(页大小+8) |
-c | 最大LEB数 | = 分区大小 / 逻辑擦除块大小 |
-p | 物理擦除块大小 | = NAND 擦除块大小 |
内核 bootargs 配置:
ubi.mtd=2root=ubi0:rootfsrootfstype=ubifs rw4.4 SquashFS + OverlayFS 适配
这种方案下,底层 SquashFS 提供只读的系统文件,上层 OverlayFS 提供可写层。常见于 OpenWrt 等路由器系统。
# 1. 制作 SquashFS 镜像mksquashfs rootfs/ rootfs.squashfs\-compxz\-no-xattrs\-no-fragments# 2. 烧录到 Flash 分区# Flash 分区布局:# | u-boot | kernel | rootfs(squashfs) | overlay(jffs2) |# 3. 内核启动后,用 overlayfs 合并可写层mount-tsquashfs /dev/mtdblock2 /rommount-tjffs2 /dev/mtdblock3 /overlaymount-toverlay overlay\-olowerdir=/rom,upperdir=/overlay/upper,workdir=/overlay/work\/mnt五、NAND Flash 适配注意事项
5.1 分区划分
NAND Flash 通常在设备树中定义分区:
&nand { partition@0 { label = "bootloader"; reg = <0x000000 0x100000>; /* 1MB */ }; partition@100000 { label = "kernel"; reg = <0x100000 0x500000>; /* 5MB */ }; partition@600000 { label = "rootfs"; reg = <0x600000 0x2000000>; /* 32MB */ }; partition@2600000 { label = "userdata"; reg = <0x2600000 0x1A00000>; /* 26MB */ }; };5.2 硬件 ECC 配置
NAND Flash 需要配置 ECC(Error Correction Code)校验方式:
# 查看NAND Flash信息cat/proc/mtd dev: size erasesize name mtd0: 04000000 00020000"nand-flash"mtd1: 00100000 00020000"bootloader"mtd2: 00500000 00020000"kernel"mtd3: 02000000 00020000"rootfs"总结
文件系统选型的核心原则:存储介质决定文件系统类型。eMMC/SD 用 ext4,NAND 用 UBIFS 或 JFFS2,NOR 小容量用 JFFS2。如果需要只读保护,SquashFS + OverlayFS 是最佳组合。选对文件系统只是第一步,正确配置分区参数(页大小、擦除块大小、LEB数量)才是成功适配的关键。下一阶段就是打包烧录,让系统真正在板子上跑起来。