4、RMC存储系统:eMMC与NVMe SSD的选择、启动引导流程、文件系统选型(UBIFS vs ext4)

存储系统,说白了就是RMC的“记忆体”。它既要存代码,又要存数据,还得保证掉电不丢。我这些年经手的项目,至少有一半的稳定性问题,最后都追查到了存储选型或配置上。这一章,咱们就把eMMC、NVMe SSD、启动引导和文件系统这几个硬骨头啃下来。

4.1 eMMC vs NVMe SSD:选谁?

先问个问题:你的RMC是跑在工业现场,还是数据中心?这个问题的答案,基本就决定了你的存储方向。

eMMC,全称是embedded MultiMediaCard。它把Flash控制器和NAND Flash颗粒封装在一起,对外提供标准接口。我习惯把它看作“大号SD卡”,但可靠性高得多。

  • 优点:成本低、体积小、接口简单(通常是8线并行或SDIO)。
  • 缺点:性能上限低(顺序读写约300MB/s)、寿命受制于NAND颗粒。
  • 适用场景:工业控制、边缘网关、车载设备。这些地方对成本敏感,对性能要求不高。

NVMe SSD,Non-Volatile Memory Express,走的是PCIe通道。它把延迟压到了微秒级,吞吐量能到GB/s级别。

  • 优点:性能炸裂、延迟极低、支持多队列并行。
  • 缺点:贵、功耗高、需要PCIe控制器支持。
  • 适用场景:AI推理服务器、高速数据采集、核心网络设备。

我的选型原则

  • 如果系统启动时间要求小于5秒,且需要频繁写入日志,我建议直接上NVMe。
  • 如果成本是第一约束,且写入量不大(每天几十MB级别),eMMC完全够用。
  • 千万别在eMMC上跑数据库!我曾经见过一个项目,用eMMC存SQLite,三个月后eMMC就挂了。
对比项 eMMC NVMe SSD
接口 MMC/SDIO PCIe
顺序读 ~300 MB/s ~3500 MB/s
随机IOPS ~10K ~500K
典型功耗 0.5W - 1W 3W - 8W
成本(每GB)
寿命 中等(取决于TBW) 长(通常有DRAM缓存)

4.2 启动引导流程:从ROM到Kernel

RMC的启动,不是一蹴而就的。它像接力赛,一棒接一棒。我画了一张图,帮你理清这个流程。

RMC启动引导流程 阶段1: ROM Boot 固化在芯片ROM中 阶段2: SPL 初始化DDR、时钟 阶段3: U-Boot 加载Kernel、DTB 阶段4: Kernel 挂载根文件系统 存储介质 eMMC / NAND Flash NVMe SSD / SATA SD卡 / USB SPL = Secondary Program Loader,即二级引导程序 U-Boot负责从存储介质中读取Kernel镜像和设备树 关键:SPL必须足够小(通常<64KB),因为它在SRAM中运行

嗯,这里要注意几个细节:

  • ROM Boot:芯片上电后,CPU从ROM中执行固化代码。它初始化最基本的硬件(比如时钟、引脚),然后去固定的位置找SPL。这个位置通常是eMMC的boot分区,或者NAND的block 0。
  • SPL:Secondary Program Loader。它很小,因为此时DDR还没初始化,只能在芯片内部的SRAM里跑。SPL的任务就是初始化DDR,然后把U-Boot从存储介质加载到DDR中。
  • U-Boot:这才是真正的引导加载程序。它提供命令行,可以设置启动参数、加载Kernel、设备树(DTB)。我习惯在U-Boot里加一个“启动计数”功能,用于系统升级失败后的回滚。
  • Kernel:最后,U-Boot把控制权交给Kernel。Kernel挂载根文件系统,启动init进程。

避坑指南:我曾经在eMMC的boot分区里放SPL,结果因为eMMC的boot分区默认是只读的,导致第一次烧录后无法更新。后来我改用U-Boot的“mmc bootbus”命令,把boot分区配置为可写。记住,eMMC的boot分区需要手动设置“Extended CSD”寄存器才能写入。

4.3 文件系统选型:UBIFS vs ext4

文件系统选型,说白了就是“你打算怎么管这些数据”。我见过太多人直接在NAND上跑ext4,结果没几个月就出现坏块导致系统崩溃。这里面的门道,我跟你聊聊。

4.3.1 UBIFS:NAND Flash的亲生儿子

UBIFS是专门为NAND Flash设计的。它直接运行在MTD(Memory Technology Device)层之上,不需要FTL(Flash Translation Layer)。

  • 优点:支持磨损均衡、坏块管理、掉电安全。压缩是内置的,能省不少空间。
  • 缺点:不支持快照、不支持文件追加写优化。挂载速度比ext4慢。
  • 适用场景:eMMC、NAND Flash作为根文件系统。

UBIFS的挂载命令很简单:

# 假设MTD分区是mtdblock2
mount -t ubifs /dev/ubi0_0 /mnt/rootfs

# 或者通过UBI设备
ubiattach -m 2 -d 0
mount -t ubifs ubi0:rootfs /mnt/rootfs

4.3.2 ext4:通用型选手

ext4是Linux上最成熟的文件系统。它需要底层块设备支持随机读写,所以通常跑在NVMe SSD或SD卡上。

  • 优点:性能好、支持日志、支持快照、工具链成熟。
  • 缺点:不支持坏块管理(依赖底层设备)、掉电时日志恢复可能丢数据。
  • 适用场景:NVMe SSD、SD卡、SATA硬盘。

我的建议

  • 如果存储介质是eMMC或NAND Flash,必须用UBIFS。别问我为什么,我见过太多ext4在NAND上跑出坏块后整个分区挂掉的案例。
  • 如果存储介质是NVMe SSD,用ext4。NVMe SSD自带FTL和坏块管理,ext4的日志功能反而能提供更好的数据一致性。
  • 如果存储介质是SD卡,用ext4 + noatime。SD卡的随机写入性能很差,noatime可以减少不必要的写操作。
对比项 UBIFS ext4
底层依赖 MTD + UBI 块设备(MMC/SD/NVMe)
坏块管理 内置 无(依赖底层)
磨损均衡 支持 不支持
掉电安全 好(日志结构) 中等(日志可能损坏)
压缩 内置(LZO/zlib) 不支持
挂载速度 慢(需扫描)
典型应用 eMMC根文件系统 NVMe SSD数据分区

警告:不要在UBIFS上使用“sync”挂载选项。UBIFS的日志结构设计本身已经保证了掉电安全,加sync反而会大幅降低性能。我曾经在一个项目中加了sync,结果写入速度从5MB/s掉到了200KB/s,排查了三天才发现是这个问题。

最后说一句,文件系统的选型没有绝对的对错,但一定要匹配你的硬件特性。eMMC配UBIFS,NVMe配ext4,这是最稳妥的组合。如果你非要在eMMC上跑ext4,记得加上“discard”选项,让文件系统主动通知eMMC哪些块可以回收。嗯,就这样。


专注资料整理