18、存储系统移植:eMMC/UFS驱动适配、F2FS文件系统优化、存储性能测试、加密存储(FBE/FDE)配置

存储系统,说白了就是车机的大脑记忆体。Android Automotive 对存储的要求比手机还苛刻——你想想看,车机要连续跑好几年,不能卡顿,不能掉电丢数据。我这些年调过的存储问题,从 eMMC 到 UFS,从 ext4 到 F2FS,踩过的坑真不少。今天咱们就把这块彻底讲透。

18.1 eMMC vs UFS:选型与驱动适配

先聊硬件选型。eMMC 和 UFS 都是 NAND Flash 的封装方案,但差异很大。

对比项 eMMC 5.1 UFS 2.1/3.1
接口协议 并行(8位) 串行(M-PHY)
全双工 不支持 支持
典型顺序读 ~250 MB/s ~800 MB/s(UFS 2.1)
随机读写 IOPS ~10K ~30K+
Linux 驱动 mmc_block / mmc_core ufshcd / ufs-qcom

我在一个项目中遇到过客户坚持用 eMMC 做 4K 视频录制。结果呢?写入延迟一高,掉帧严重。后来换了 UFS 3.1,问题直接解决。所以我的建议是:如果车机有高码率视频或频繁 OTA 场景,别省那几块钱,直接上 UFS。

eMMC 驱动适配要点

Linux 内核里,eMMC 走的是 MMC 子系统。你需要关注这几个点:

  • 设备树配置:在 arch/arm64/boot/dts/ 里添加 mmc 节点,设置 bus-width、non-removable、no-sd 等属性。
  • HS400 模式:i.MX8 系列支持 HS400,但需要 tuning。我建议先降级到 HS200 验证稳定性,再切 HS400。
  • Cache 与 Packed Command:eMMC 5.0 以上支持,能提升写入性能。但注意——有些旧批次芯片有 bug,开了会丢数据。

UFS 驱动适配要点

UFS 驱动相对复杂,因为涉及 UniPro 和 M-PHY 两层协议。以 i.MX8QM 为例:

// 内核配置
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFS_QCOM=y
CONFIG_SCSI_UFSHCD_PLATFORM=y

// 设备树示例
&ufs {
    status = "okay";
    ref-clk-freq = <38400000>;
    lanes-per-direction = <2>;
};

嗯,这里要注意:UFS 的参考时钟必须精确,否则链路训练会失败。我调试时吃过这个亏,折腾了两天才发现是晶振偏差超了 50ppm。

18.2 F2FS 文件系统优化

Android 从 8.0 开始推荐 F2FS 替代 ext4。为什么?因为 F2FS 是专门为 NAND Flash 设计的,能减少写放大,提升随机性能。

我个人习惯在 /data 分区用 F2FS,/system/vendor 用 ext4(只读分区没必要上 F2FS)。

F2FS 挂载参数优化

# 推荐挂载参数
mount -t f2fs /dev/block/mmcblk0p4 /data \
    -o noatime,nodiratime,inline_xattr,inline_data,flush_merge,extent_cache
  • inline_xattr:将小文件的扩展属性内联到 inode,减少 I/O。
  • flush_merge:合并多个 flush 命令,降低延迟。
  • extent_cache:缓存 extent 映射,提升大文件顺序读性能。
我的经验:F2FS 的 GC(垃圾回收)在空间利用率超过 90% 时性能会急剧下降。建议预留 10%~15% 的 over-provisioning 空间。在分区时就把 f2fs 的 reserved-blocks 设大一点。

F2FS 与 OTA 升级

OTA 升级时,系统要解压并写入大量小文件。F2FS 在这方面比 ext4 快 30%~50%。但有个坑——如果升级中途掉电,F2FS 的恢复速度比 ext4 慢。我建议在 OTA 脚本里先执行 fsck.f2fs -f 做一次强制检查。

18.3 存储性能测试

光调参数不行,得用数据说话。我常用的测试工具和指标:

测试项 工具 目标值(UFS 2.1)
顺序读 fio --rw=read --bs=1M > 700 MB/s
顺序写 fio --rw=write --bs=1M > 400 MB/s
随机读 4K fio --rw=randread --bs=4K > 20K IOPS
随机写 4K fio --rw=randwrite --bs=4K > 15K IOPS
混合读写 fio --rw=randrw --rwmixread=70 延迟 < 5ms

跑测试时,我建议用 --direct=1 绕过 page cache,测出真实硬件性能。另外,记得先 echo 3 > /proc/sys/vm/drop_caches 清空缓存,否则数据不准。

注意:不要在车机量产版本上跑破坏性测试(比如连续写满全盘)。我曾经在客户现场跑了一晚上 fio,结果把 eMMC 的 write endurance 耗掉了 2%,被客户骂了一顿。

18.4 加密存储:FBE 与 FDE

Android Automotive 要求全盘加密,但有两种方案:FDE(全盘加密)和 FBE(基于文件的加密)。

FDE(Full Disk Encryption)

FDE 是旧方案,加密整个 /data 分区。启动时输入密码,解密整个分区。缺点很明显——开机慢,而且一旦解锁,所有文件都可见。

配置方式:在 BoardConfig.mk 里设置 BOARD_USES_QCOM_FDE := true,并在 fstab 里加 encryptable=footer

FBE(File Based Encryption)

FBE 是 Google 推荐的新方案。每个文件有自己的密钥,不同用户/配置文件之间隔离。车机里特别有用——你可以让导航数据加密,但媒体库不加密,提升性能。

配置 FBE 需要内核支持:

# 内核必须开启
CONFIG_FS_ENCRYPTION=y
CONFIG_DM_DEFAULT_KEY=y
CONFIG_KEY_DH_OPERATIONS=y

# fstab 示例
/dev/block/mmcblk0p4  /data  f2fs  noatime,nosuid,nodev,fileencryption=aes-256-xts

Android 12 以上还支持 metadata encryption,用单独的密钥加密文件系统元数据。我建议开启,因为元数据泄露也能暴露文件结构。

避坑指南:我曾经在切换 FBE 时忘记更新 init.rc 里的 vold.decrypt 属性,导致开机后 vold 无法启动,卡在加密界面。排查了一整天,最后发现是 sepolicy 没给 vold 访问密钥环的权限。

18.5 知识体系总览

下面这张图总结了存储系统移植的核心模块和流程:

存储系统移植知识体系 硬件选型 驱动适配 文件系统 eMMC / UFS 选型 带宽、延迟、成本 HS400 / UniPro 协议 设备树配置 驱动与调试 mmc_block / ufshcd 链路训练 / Tuning Cache 与 Packed Cmd F2FS / ext4 挂载参数优化 GC 与 Over-provisioning OTA 兼容性 性能测试 (fio) 加密存储 (FBE/FDE) 稳定性验证 从硬件选型到驱动适配,再到文件系统优化与安全加密,形成完整移植链路

这张图把整个存储移植的脉络理清了。从左到右,从硬件到软件,从性能到安全。你移植的时候,就按这个顺序一步步来,基本不会漏项。


好了,存储系统这块内容不少,但核心就三点:选对硬件、调好驱动、配好加密。下一节咱们聊显示系统移植,那又是另一番天地了。