4. QNX Flash存储管理:Flash存储特性、QNX Flash文件系统(ETFS)、Flash磨损均衡与垃圾回收

好,咱们进入第四章。这一章聊的是Flash存储管理,说白了就是QNX系统里怎么跟Flash芯片打交道。我在嵌入式这行摸爬滚打十几年,Flash这块踩过的坑真不少。你想想看,一个设备可能要在户外跑五年十年,Flash要是先挂了,那整个系统就废了。所以这一章的内容,我建议你认真看。

4.1 Flash存储特性:你得先懂它的脾气

Flash不是普通硬盘。它有几个非常特殊的脾气,你不顺着它来,它就给你颜色看。

第一个特性:写之前必须先擦除。 普通RAM或者硬盘,你可以直接覆盖写。Flash不行。你得先把整个块(Block)擦成全1,然后再往里写。我当年第一次用Flash存配置参数,直接调write()函数,结果数据死活写不进去。查了半天才发现,原来那片区域之前写过数据,必须先擦除。

第二个特性:擦除次数有限。 每个Flash块都有寿命,一般是10万次到100万次擦写。听起来很多对吧?但如果你每秒写一次日志,一年就3153万次了。所以磨损均衡(Wear Leveling)不是可选项,是必选项。

第三个特性:读写单位不一样。 读可以按字节,写通常按页(Page),擦除按块(Block)。常见的NAND Flash,一页可能是2KB或4KB,一块可能是64页或128页。这个差异会导致很多设计上的麻烦。

特性 NOR Flash NAND Flash
读取速度 快(支持XIP) 较慢
写入速度
擦除次数 约10万次 约10万次
坏块管理 基本不需要 必须
典型用途 代码存储、XIP执行 大容量数据存储

核心要点: QNX系统里,Flash管理不是简单的文件读写。你得考虑擦除、磨损、坏块这三个老大难问题。ETFS就是QNX专门为解决这些问题设计的。

4.2 QNX Flash文件系统(ETFS):专为嵌入式打造的方案

ETFS,全称是Embedded Transactional File System。这个名字里有两个关键词:「Embedded」说明它是为嵌入式场景设计的,「Transactional」说明它支持事务——也就是写操作要么全部成功,要么回滚到之前的状态。

我个人习惯把ETFS理解为「带保险的Flash文件系统」。为什么这么说?

第一,它支持原子操作。 你在写一个文件时突然断电了,重启后文件要么是完整的旧版本,要么是完整的新版本。不会出现半截文件。我在做车载信息娱乐系统时,有一次客户的车在OTA升级过程中被拔了电瓶。重启后系统居然还能正常启动,就是因为ETFS的事务机制保住了文件系统的完整性。

第二,它自带磨损均衡。 ETFS会自动把数据分散写到不同的物理块上,避免某些块被频繁擦写而提前报废。你不需要自己写磨损均衡算法,ETFS在底层帮你搞定了。

第三,它支持坏块管理。 NAND Flash出厂时就可能有坏块,使用过程中还会产生新的坏块。ETFS会自动检测并跳过坏块,把数据写到好块上。

小提示: ETFS的挂载命令很简单:mount -T io-blk blk device=/dev/flash0 mountpoint=/fs/etfs。但要注意,挂载前得先确认Flash驱动已经正确初始化了。

ETFS的典型应用场景包括:

  • 系统配置参数的持久化存储
  • 日志文件的循环写入
  • OTA升级包的临时存放
  • 用户数据的读写

嗯,这里要注意一点:ETFS不是万能的。如果你需要存储大文件(比如几百MB的视频),ETFS的性能可能不如专门的Flash文件系统。它更适合小文件、频繁读写的场景。

4.3 Flash磨损均衡:让Flash活得更久

磨损均衡,说白了就是「雨露均沾」。你不能老盯着一个块使劲写,得让所有块轮流干活。

磨损均衡有两种策略:

  • 动态磨损均衡: 只在写入时做均衡。新数据来了,找个擦除次数最少的块写进去。
  • 静态磨损均衡: 连那些很久没动的「冷数据」块也会被搬走,让它们也能被擦写一次。

ETFS默认使用动态磨损均衡。如果你对Flash寿命要求特别高,可以配置静态磨损均衡。代价是性能会稍微下降,因为后台要搬数据。

警告: 千万不要在ETFS挂载的目录下频繁写同一个文件!我曾经见过一个项目,日志文件每秒写一次,结果三个月后Flash就挂了。后来改成循环写入多个文件,寿命延长了十倍。

磨损均衡的效果可以用一个指标来衡量:均衡因子。理想值是1,表示所有块的擦除次数完全一样。实际中能做到0.8以上就算不错了。

4.4 垃圾回收:Flash的「大扫除」

垃圾回收(Garbage Collection)是Flash文件系统里最容易被忽视但又最重要的机制。你想想看,Flash擦除是按块来的,但写数据是按页来的。一个块里可能有些页是有效数据,有些页是无效数据(被标记删除)。垃圾回收就是把这些有效数据搬走,然后擦除整个块,腾出空间。

ETFS的垃圾回收是自动的,不需要你手动触发。但有几个参数你可以调:

  • 回收阈值: 当空闲块数量低于这个值时,触发垃圾回收。默认是总块数的10%。
  • 回收力度: 每次回收多少个块。默认是1个。

我曾经在一个项目中遇到过性能抖动的问题。系统平时跑得好好的,但每隔几分钟就会卡顿一下。查了半天,发现是垃圾回收在后台搬数据,占用了Flash带宽。后来我把回收阈值调高了一点,让垃圾回收更早开始、更平缓地进行,卡顿问题就解决了。

避坑指南: 垃圾回收期间,Flash的读写性能会下降。如果你的系统对实时性要求很高(比如音频播放),建议把垃圾回收的优先级调低,或者安排在系统空闲时进行。

4.5 实战建议:如何用好ETFS

讲了这么多理论,最后给几条实战建议:

  1. 分区规划要提前做。 把系统分区、数据分区、日志分区分开。系统分区只读挂载,数据分区用ETFS,日志分区可以用循环写入的方式。
  2. 文件大小要控制。 ETFS对小文件(几KB到几百KB)支持最好。大文件建议用其他方案。
  3. 定期检查Flash健康状态。 QNX提供了fsysinfo命令,可以查看ETFS的磨损情况、坏块数量等。我建议在系统里加一个监控任务,每天检查一次。
  4. 预留足够的空闲空间。 ETFS需要至少10%-20%的空闲空间来做垃圾回收和磨损均衡。空间用得太满,性能会急剧下降。

好了,这一章的内容就到这里。Flash存储管理看起来简单,但实际项目中坑很多。记住一句话:尊重Flash的物理特性,别把它当硬盘用。 下一章我们会讲QNX的OTA升级方案,到时候ETFS会扮演重要角色。