4、固件镜像格式:raw image、squashfs、ubifs、jffs2的区别与选择
做CPE量产固件打包,选文件系统这事儿,我踩过的坑真不少。
你想想看,一个路由器或者光猫,Flash空间就那么点,既要跑系统,又要存配置,还得考虑掉电保护。选错了格式,轻则空间不够,重则启动不了。
今天咱们就把这四种最常见的格式掰开揉碎了讲。嗯,都是实战经验。
4.1 raw image:最原始的“裸”镜像
说白了,raw image就是一块二进制数据的直接拷贝。没有文件系统,没有元数据,就是纯粹的“从地址A到地址B,按字节搬过去”。
什么时候用?
- Bootloader(比如U-Boot)的镜像。它不需要文件系统,直接加载到内存就跑。
- 一些极其简单的裸机程序。
- 作为其他文件系统的“容器”,比如把squashfs打包进raw分区。
核心特点:
- 结构最简单,没有之一。
- 烧录速度最快,因为不需要解析任何目录结构。
- 无法管理文件,不能增删改。
- 通常配合固定偏移量使用。
我的习惯: 做量产烧录时,我会把Bootloader和分区表做成一个raw image。这样烧录一次,整片Flash的布局就固定了,省事。
4.2 squashfs:只读的压缩文件系统
这是CPE设备里最常见的根文件系统格式。为什么?因为它压缩率高,而且是只读的,保证了系统文件的完整性。
我在项目中遇到过,有人试图用JFFS2做根文件系统,结果每次启动都要做完整性检查,慢得让人抓狂。换成squashfs后,启动时间直接砍半。
核心特点:
- 高压缩比: 一个100MB的根文件系统,压缩后可能只有30MB。这对Flash容量有限的CPE设备来说,太重要了。
- 只读: 系统文件不会被意外篡改。配合Overlay机制(比如overlayfs),把可写部分挂载到另一个分区,既保证了系统安全,又实现了配置持久化。
- 支持随机读取: 读取文件时不需要解压整个镜像,按需解压。
注意: squashfs是只读的。如果你需要动态修改系统文件(比如安装软件包),必须配合Overlay或者单独的可写分区。我曾经见过有人试图直接挂载squashfs然后写文件,结果系统直接报错。
4.3 ubifs:专为NAND Flash设计的读写文件系统
UBIFS是UBI(Unsorted Block Images)文件系统的一部分。它专门针对NAND Flash的特性做了优化。
你可能会问:“为什么不用JFFS2?” 嗯,这里有个历史原因。JFFS2在早期的NAND Flash上表现还行,但随着NAND容量增大、页大小从512字节变成4K甚至8K,JFFS2的挂载时间和内存占用就成了大问题。
UBIFS的优势:
- 支持大容量: 对GB级别的NAND Flash支持良好。
- 挂载速度快: 不需要像JFFS2那样扫描整个介质来重建日志。
- 磨损均衡: 通过UBI层实现,延长Flash寿命。
- 掉电安全: 日志结构保证意外掉电不会损坏文件系统。
实战建议: 如果你的CPE设备使用NAND Flash,并且需要频繁读写配置或日志文件,UBIFS是首选。我个人习惯把UBIFS用于数据分区(比如/overlay或/data)。
4.4 jffs2:老牌的日志文件系统
JFFS2(Journalling Flash File System version 2)是Linux上最早用于NOR/NAND Flash的日志文件系统之一。现在用得少了,但老设备上还能见到。
特点:
- 日志结构: 所有写入都是追加到日志末尾,掉电不会丢失数据。
- 压缩: 支持zlib等压缩算法。
- 挂载慢: 这是最大的痛点。挂载时需要扫描整个Flash来重建文件系统树。对于256MB以上的NAND,挂载时间可能长达几十秒。
- 内存占用高: 扫描过程中需要维护大量的节点信息。
避坑指南: 我曾经在一个老项目里接手过JFFS2的根文件系统。每次设备重启,挂载都要等30秒以上。后来我把它换成了squashfs+overlay,启动时间从45秒降到了8秒。所以,除非你维护的是10年前的设备,否则别用JFFS2做根文件系统。
4.5 如何选择?一张表说清楚
| 特性 | raw image | squashfs | ubifs | jffs2 |
|---|---|---|---|---|
| 读写属性 | 只读(裸数据) | 只读 | 可读写 | 可读写 |
| 压缩 | 无 | 高压缩比 | 支持 | 支持 |
| 挂载速度 | 无需挂载 | 快 | 快 | 慢(容量越大越慢) |
| 掉电安全 | 不适用 | 只读,天然安全 | 日志结构,安全 | 日志结构,安全 |
| 适用场景 | Bootloader、分区表 | 根文件系统(只读) | 数据分区、日志分区 | 老旧设备、小容量NOR Flash |
| 典型Flash类型 | NOR/NAND | NOR/NAND | NAND(大容量) | NOR(小容量) |
4.6 我的推荐组合
做CPE量产固件,我一般这样搭配:
- Bootloader分区: raw image。简单直接,烧录一次,永不修改。
- 内核分区: raw image或者squashfs。如果内核不大,raw image就行;如果内核需要压缩,用squashfs。
- 根文件系统: squashfs。只读,安全,压缩率高。配合overlayfs把可写部分挂载到UBIFS分区。
- 数据分区(配置、日志): UBIFS。读写性能好,掉电安全,支持大容量。
一个小技巧: 在量产打包脚本里,我会先用squashfs打包根文件系统,然后把它和内核、设备树一起打包成一个raw image。这样烧录时只需要烧录一个文件,简单又不容易出错。
好了,这四种格式的区别和选择,基本就这些了。记住一句话:只读用squashfs,读写用UBIFS,老设备用JFFS2,裸数据用raw image。按这个原则选,基本不会出大问题。