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量产固件,我一般这样搭配:

  1. Bootloader分区: raw image。简单直接,烧录一次,永不修改。
  2. 内核分区: raw image或者squashfs。如果内核不大,raw image就行;如果内核需要压缩,用squashfs。
  3. 根文件系统: squashfs。只读,安全,压缩率高。配合overlayfs把可写部分挂载到UBIFS分区。
  4. 数据分区(配置、日志): UBIFS。读写性能好,掉电安全,支持大容量。

一个小技巧: 在量产打包脚本里,我会先用squashfs打包根文件系统,然后把它和内核、设备树一起打包成一个raw image。这样烧录时只需要烧录一个文件,简单又不容易出错。

好了,这四种格式的区别和选择,基本就这些了。记住一句话:只读用squashfs,读写用UBIFS,老设备用JFFS2,裸数据用raw image。按这个原则选,基本不会出大问题。