Lecture 26: 闪存(Flash Memory)

目录 · ← l18 · l20 →

Lecture 26: 闪存(Flash Memory)

概述

闪存(SSD)已取代磁盘成为主流存储。本讲从闪存单元的物理特性(写不对称、擦除单位、磨损)出发,解释为什么闪存不能直接当磁盘用,进而介绍闪存转换层(FTL):块映射、页头(A/W/G 位)、垃圾回收、写放大(write amplification)磨损均衡(wear leveling),以及文件系统与 FTL 的协作(TRIM)。

核心概念与系统机制图解

闪存单元特性

对比:
  与磁盘比: 无活动部件(可靠、抗冲击); 随机访问延迟低100-1000倍; 每比特成本高3-10倍
  与DRAM比: 非易失(断电保留); 每比特成本低5-20倍; 慢100-1000倍
单元行为:
  ● 读: 快(~10-100微秒), 以页(page)为单位访问(4-16KB, 更像磁盘)
  ● 写(1→0): 较快(~100-1000微秒)
  ● 写(0→1): 很慢(~1000-10000微秒)!
  ● 必须先"擦除(erase)"(写成全1)才能重写
  ● 擦除以"擦除单元(erase unit)"为单位(1-8MB, 含很多页), 约2ms
  ● 擦除会磨损: 每个擦除单元只能擦除约100-100,000次 → 磨损(wear out)

为什么闪存不能直接当磁盘用 → FTL

  • 现有文件系统按”可原地覆写块”设计,与闪存”擦除-重写”模型冲突。
  • 闪存转换层(Flash Translation Layer, FTL):SSD 内的软件,向文件系统暴露线性块数组(虚拟块号),内部把虚拟块映射到物理页。代价:性能折损、空间浪费、实现专有。

直接映射 FTL(简单但差)

块N → 物理页N; 写块N = 读整个擦除单元 → 擦除 → 重写整个单元
问题: 每次写加2ms擦除; 反复写同一块快速磨损; 崩溃丢旧数据
(只用于廉价U盘+FAT)

块映射 FTL(现代做法)

维护"块映射": 虚拟块 → 物理页
读: 查映射表取物理位置
写: 找空闲已擦除页 → 写入 → 更新映射 → 旧页标记为垃圾
每页头部记录元数据:
  A(Allocated)位: 1=空闲 0=已分配
  W(Written)位:  1=未写(全1) 0=已写
  G(Garbage)位:  0=不再使用, 复用前必须擦除
状态机: 111(刚擦除) → 011(已分配未写) → 001(已写成功) → 000(已删除/垃圾)
  (011 状态用于检测写块过程中崩溃)
崩溃恢复: 扫描所有页头, 重建映射表与空闲表

垃圾回收与写放大

问题: 垃圾页堆积 → 容量缩水
垃圾回收: 找垃圾多的擦除单元 → 把活页复制到干净单元(更新映射) → 擦除旧单元
写放大: 每写入 1 个新数据单元, 实际写入 1/(1-U) 个单元(U=平均利用率)
  U=0.5 → 写放大2;  U=0.9 → 10;  U=0.99 → 100
改善: 让利用率呈"双峰分布"——大多数单元接近满(U≈1)、少数接近空(U≈0);
     按"温度"分仓: 热块(频繁覆写)与冷块分开存放; 垃圾回收专挑热而空的单元

磨损均衡(Wear Leveling)

  • 热擦除单元磨损快 → 偶尔对冷单元做垃圾回收(收不回多少空间,但得到一个”新”单元)→ 把擦除分散到整个设备。

FTL 与文件系统协作

  • 重复映射:文件块 → 逻辑磁盘块 → 闪存页,两层翻译浪费;早期”闪存优化文件系统”因便宜 FTL 的普及而失败。
  • 信息缺失:FTL 不知道 OS 何时释放块(只有覆写时才知道)→ 垃圾回收常搬运已删除文件的数据块。
  • TRIM 命令:文件系统主动告知闪存”这些块已释放” → FTL 提前标记为垃圾。
  • 趋势:当前文件系统与 FTL 共存,由 FTL 负责磨损均衡、坏块、擦除调度;闪存鼓励”不在原地更新(out-of-place update)”的文件系统设计。

代码示例与系统调用解说

示例:TRIM / discard 的用户可见行为(Linux)

# 创建文件 → 写入 → 删除: 让 SSD 知道块已释放
echo "data" > f
sync
rm f

# 手动 TRIM (fstrim 对所有挂载 FS 发送 discard)
sudo fstrim -v /
# 输出: /: 12.3 GiB (13201264640 bytes) trimmed

【代码做了什么?】 rm 删除文件后,fstrim 向 SSD 发送 TRIM 命令,告知哪些块不再需要保留。

【系统机制透视】

  • 没有 TRIM 时,FTL 只有等块被覆写才知道旧副本是垃圾;删除的文件块会被垃圾回收白白搬运(浪费写入寿命与性能)。
  • TRIM 是文件系统 ↔ FTL 的信息通道:文件系统把”逻辑释放”翻译成”物理可回收”,让写放大与磨损更可控——这是”分层系统间信息泄露/传递”的典型例子(Lecture 28 的”分层”主题)。

关键要点

  1. 闪存”1→0 快、0→1 需擦除、擦除以大单元为单位、擦除磨损”——与磁盘模型根本不同。
  2. FTL 把闪存伪装成线性块磁盘;核心是块映射 + 页头位(A/W/G)+ 崩溃重建。
  3. 垃圾回收造成写放大 1/(1-U);双峰利用率分布可显著改善。
  4. 磨损均衡把擦除分散到全设备,延长寿命。
  5. TRIM 让文件系统告知 FTL 释放的块,减少无效搬运。

常见陷阱与注意事项

  • 把闪存当磁盘原地覆写:频繁小写会触发整单元擦除重写(写放大)。
  • 忽略磨损:热数据集中导致部分单元快速报废。
  • 不做崩溃处理:写页中途崩溃(A/W/G 状态机检测)需要重建机制。
  • 忘记 TRIM:删除的数据仍被 FTL 当作有效数据搬运。
  • 用磁盘思维优化 SSD 布局:寻道优化(SCAN 等)对 SSD 无意义;应优化写放大与磨损。

思考题

  1. 问题:为什么闪存写放大公式是 1/(1-U)?利用率 90% 意味着什么?
    • 答案:垃圾回收每腾出 1-U 的空间就要重写 U 的旧数据;每写入 1/(1-U) 个单元才能释放 1 个单元的空间。U=0.9 意味着每次有效写入实际消耗 10 倍的写带宽——既慢又加速磨损。
  2. 问题:TRIM 命令解决了 FTL 的什么问题?
    • 答案:FTL 无法区分”已删除的块”与”有效数据”(只能等覆写);TRIM 让文件系统在删除时主动告知,FTL 可立即把这些页标记为垃圾,避免垃圾回收搬运无用数据,降低写放大。