存储_03:FTL 闪存转换层——映射/磨损均衡/垃圾回收/坏块管理
适用人群:目标江波龙 firmware 岗,知道 NAND 有坏块、要 ECC,但被问"FTL 是干嘛的、磨损均衡怎么实现、垃圾回收搬的是什么、掉电写到一半怎么办"就答不上来的同学。这是
17_存储专栏第三篇,也是存储原厂 firmware 岗的面试核心。
读完你能得到:
① 为什么 NAND 必须套一层 FTL 才能当"硬盘"用;
② FTL 四大功能:地址映射 / 磨损均衡 / 垃圾回收 / 坏块管理;
③ 页映射 vs 块映射 vs 混合映射的取舍;
④ 异地更新、磨损均衡(动态/静态)、GC 搬页的逻辑;
⑤ 掉电保护在 FTL 里怎么落地(映射表持久化 + 原子切换);
⑥ 一段极简 FTL 写路径思路(面试能口述)。
一、为什么需要 FTL
NAND 原生有几条"反人类"特性(存储_02 讲过):
- 写前必擦,而且擦的单位(块)比写(页)大;
- 不能原地改(写只能 1→0);
- 有坏块,不能存数据;
- 寿命有限(P/E 次数),得摊着用。
如果直接把 NAND 暴露给上层(文件系统/应用),上层会崩溃——“我想改这个字节"在 NAND 上根本做不到。于是加一层软件/固件:FTL(Flash Translation Layer,闪存转换层),在 NAND 和上层之间做翻译,让上层以为自己在操作一块"普通硬盘”。
文件系统 / 应用
│ 以为在读写"逻辑块 LBA"
▼
┌──────────────┐
│ FTL │ ← 江波龙这类厂自研的核心固件
│ 映射+均衡+GC+BBM│
└──────────────┘
│ 实际操作"物理页/块 PPA"
▼
NAND Flash
一句话:FTL 就是"把难用的 NAND 伪装成好用的块设备"的那层固件。eMMC/UFS/SSD 内部的控制器里跑的就是它——这也是江波龙这种原厂的核心技术壁垒。
二、FTL 四大功能
| 功能 | 解决什么 | 怎么做的 |
|---|---|---|
| ① 地址映射 | 上层逻辑地址 ↔ 物理地址 | 维护映射表 LBA→PPA |
| ② 磨损均衡 | 所有块擦写次数均匀,延长寿命 | 动态+静态均衡 |
| ③ 垃圾回收 GC | 回收"无效页"占用的块 | 搬有效页、擦无效块 |
| ④ 坏块管理 BBM | 跳过坏块、替换保留块 | 坏块表 + 重映射 |
四件里,地址映射是地基,后三件是 NAND 专用的"续命"手段。
三、地址映射:LBA → PPA
上层给的是逻辑块地址 LBA(第几个逻辑扇区),FTL 翻译成物理页地址 PPA(实际存在 NAND 的哪一页)。
写 LBA=5 的数据:
查映射表:LBA 5 → PPA (block 3, page 7)
实际写到 (3,7)
读 LBA=5:
查表 → (3,7) → 从 NAND 读那页
3.1 三种映射粒度
| 类型 | 映射单位 | 表大小 | 灵活度 | 特点 |
|---|---|---|---|---|
| 页映射 | 逻辑页↔物理页 | 大(表项=页数) | 最高 | 随机写性能好,但 RAM 占用大 |
| 块映射 | 逻辑块↔物理块 | 小(表项=块数) | 低 | 省 RAM,但随机写要整块搬,慢 |
| 混合映射 | 数据块(块映射)+日志块(页映射) | 中 | 中 | 折中,消费级常用 |
面试常问"映射表存哪":一部分常驻 RAM(快查),完整版存在 NAND 的 spare/专用区,掉电时能恢复(见第五节)。
四、异地更新 + 垃圾回收
4.1 异地更新(Out-of-Place Write)
因为不能原地改,更新一个逻辑页时,FTL 写到新的物理页,把旧的标记为"无效":
初始:LBA 5 → PPA (3,7) [有效]
更新 LBA 5:
写到新页 (4,2),改映射 LBA 5 → (4,2)
旧页 (3,7) 标记为无效(invalid)
无效页越来越多,块里有效页变少,得回收。
4.2 垃圾回收 GC
GC 选一个有效页最少的块(victim),把里面还有用的有效页搬到别处,然后整块擦除重用:
选 victim 块 B:含 3 个有效页 + 5 个无效页
把 3 个有效页复制到空闲块
擦除 B(现在全 1,可再写)
触发时机:空间不足时强制 GC,或空闲时后台 GC(不卡前台)。GC 会带来写放大(见 存储_02),好的 FTL 要减少无效搬运。
五、磨损均衡(Wear Leveling)
5.1 为什么
如果某个逻辑块被频繁写,它对应的物理块很快到寿命。磨损均衡的目标:让所有块的擦写次数尽量平均,整体寿命最大化。
5.2 动态 vs 静态
| 类型 | 做法 | 解决 |
|---|---|---|
| 动态均衡 | 只在"被重写/重分配"的块间均衡 | 频繁写的"热"块均匀耗损 |
| 静态均衡 | 把很少改的"冷"数据也搬出来,让冷块也能被擦写 | 防止冷块永远不擦、热块先死 |
静态均衡是关键:如果不管冷数据,冷块永远 0 次擦写、热块早早报废,整体寿命起不来。好的 FTL 冷数据也要定期搬。
六、坏块管理(BBM)
接 存储_02 的坏块:FTL 维护一张坏块表,
上电:扫所有块 OOB 区,建立初始坏块表(出厂坏块)
运行中:写/擦失败 → 标记新坏块 → 从"保留块池"分配替换块
以后映射时:跳过坏块表里的块
保留块(spare/reserved blocks)是出厂时多留的冗余,专门替补坏块。坏块率在设计冗余度里就考虑进去了。
七、掉电保护:FTL 层面的"原子性"
这是车规/消费都卡死的一关。问题:GC 搬页、改映射表的过程中掉电,数据怎么办?
FTL 的做法:
- 映射表持久化:定期把映射表写回 NAND 专用区,掉电后能恢复大部分;
- 原子切换:更新数据时,先写完新页 + 新映射(存在临时区),最后一步才把"指向新映射"的指针翻过来。翻指针前掉电 → 回滚到旧版本;翻之后掉电 → 新版本已生效。中间状态不对外可见;
- 事务/日志(journal):像数据库一样,操作先记日志再执行,崩溃后重放或回滚。
这和你
07_OTA的"双 bank + 标志位切换"是同一思想:用"写完再翻指针"保证要么旧要么新、没有半成品。江波龙车规产品对掉电保护要求极高(AEC-Q100),这块是必考点。
八、一段极简 FTL 写路径(面试可口述)
/* 伪代码:写逻辑块 LBA */
ftl_write(lba, data):
ppa_new = alloc_free_page() // 从空闲页池拿一页
nand_program(ppa_new, data) // 写到新页(异地更新)
ppa_old = map[lba] // 旧物理页
map[lba] = ppa_new // 改映射
mark_invalid(ppa_old) // 旧页标记无效
if (need_wear_leveling()) // 某块擦写次数过高
wear_level_one_block() // 均衡一次
if (free_pages < threshold) // 空闲页不够
gc_one_block() // 回收一个块
if (power_loss_risk()) // 电压低/要掉电
flush_mapping_table() // 持久化映射表(原子切换)
口述时把"异地更新→标记旧无效→GC 回收→磨损均衡→掉电刷表"这条链讲顺,考官基本就认可你懂 FTL 了。
九、为什么江波龙要自研 FTL
FTL 算法直接决定三件事:
- 性能:映射粒度、GC 策略影响读写延迟;
- 寿命:磨损均衡好坏决定 NAND 能用几年;
- 可靠性:掉电保护、坏块管理决定数据会不会丢。
同样一颗 NAND,不同 FTL 跑出来寿命和速度差几倍——所以存储原厂的 FTL 是核心技术资产,必须自研、不能买现成。这就是你投江波龙 firmware 岗要懂 FTL 的根本原因。
十、面试速答
考官:FTL 是干嘛的?
你:NAND 不能原地改、擦单位大、有坏块、寿命有限,不能直接当硬盘用。FTL 在 NAND 和上层之间做翻译,提供四大功能:地址映射、磨损均衡、垃圾回收、坏块管理,让上层以为在读写普通块设备。eMMC/UFS/SSD 控制器里跑的就是它。
考官:磨损均衡怎么实现?
你:分动态和静态。动态只在被重写的块间均衡擦写次数;静态还会把很少改的冷数据搬出来,让冷块也能被擦写,防止热块先报废、整体寿命最大化。
考官:掉电写到一半怎么办?
你:FTL 用异地更新+原子切换——数据先写新页,最后一步翻映射指针才生效,翻之前掉电回滚旧版、之后掉电是新版,没有半成品;映射表也会定期持久化。
十一、总结
| 要点 | 内容 |
|---|---|
| FTL 作用 | 把 NAND 伪装成块设备,四大功能 |
| 映射 | LBA→PPA,页/块/混合三种粒度 |
| 异地更新 | 更新写新页、旧页标记无效 |
| GC | 搬有效页、擦无效块,有写放大 |
| 磨损均衡 | 动态+静态,所有块擦写趋平均 |
| BBM | 坏块表+保留块替补 |
| 掉电保护 | 映射表持久化+原子切换 |
一句话总结:FTL 是 NAND 的"操作系统"——用地址映射承接上层、用异地更新+GC 管理空间、用磨损均衡延长寿命、用坏块管理避开坏区、用原子切换扛掉电,四件套缺一不可,也是存储原厂 firmware 的核心竞争力。
FTL 算法细节(如 DFTL、FAST 等学术论文方案)以各厂实现为准,本文讲通用四件套与工程取舍。映射表 RAM/NAND 分工、保留块比例等都因器件容量而异。
本站相关:存储_02(NAND 坏块/ECC/寿命)、07_固件升级与OTA(双 bank 原子切换)、存储_05(掉电保护深入)。
下一篇:存储_04_接口与协议——SPI_NOR_QSPI与SDIO_eMMC命令
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐
所有评论(0)