在固态硬盘(SSD)中,FTL(全称:Flash Translation Layer,闪存转换层)是一项核心技术。FTL位于固态硬盘的控制器中,负责管理主机和闪存之间的数据交互,对SSD的性能(Performance)和可靠性(Reliability)起着至关重要的作用。
FTL涉及多个关键功能模块,包括:
映射表(Mapping Table)
坏块管理(Bad Block Management)
垃圾回收(Garbage Collection)
磨损均衡(Wear Leveling)
错误管理(Error Handling)
等等
为了更好地理解FTL的原理,需要掌握以下闪存的基本特性:
数据操作方式:
擦除操作将数据置为1,写操作将数据置为0。
操作单元:
擦除操作的最小单元是Block(块),写操作的最小单元是Page(页)。
一个Block由多个Page组成。
写入限制:
在Page写入数据前,必须先擦除Page所在的Block。
闪存有一个重要特性:在Page写入数据之前必须要将Page所在的Block擦除。举例来说,假如将 1.txt 的内容保存在 block 1 page 1上,要修改时,需要先将block1擦除掉然后再写入page1中。这样会带来两个问题:
写性能很差,写的时间为“擦除block的时间”加上“写入page的时间”。
对block频繁的擦写操作,会让block很快变成坏块,无法使用。
而引入「映射表」可以很好地解决这个问题:数据更新时,不写入原来的Page,而是重新映射写入一个新的Page。
映射表可结合下图理解,虚线上方表示逻辑地址(Logical Block Address),下方表示物理地址(Phygical Block Address),在FTL中,映射表将逻辑地址与物理地址关联起来。这样,从操作系统视角看,存储空间是连续的(A flat block device),易于管理;而实际存储的物理地址,则由FTL负责管理。
映射粒度分为块映射、页映射和混合映射。简单对比如下:
映射粒度 | 优势 | 劣势 | 应用场景 |
---|---|---|---|
块映射 | 所需空间小;连续大尺寸的读写性能较好 | 小尺寸的写性能非常糟糕,缩短SSD的使用寿命 | U盘 |
页映射 | 性能好 | 映射表占用内容大 | SSD |
混合映射 | 性能与空间需求居中 | 设计复杂 |
通过映射表,FTL充当操作系统和闪存之间的“翻译官”,其完整的写流程如下:
操作系统发送指令给SSD,要求在逻辑地址0上,写入大小为1的数据“A”。FTL层接受该指令,将数据写入物理地址0上,并在L2P表(Logical to Phygical)中记录映射关系:逻辑地址0 -> 物理地址0。
操作系统发送指令给SSD,要求从逻辑地址4开始,写入大小为12的数据“BCDEFGHIJKLM”。FTL接受该指令,将数据写入物理地址1~12,并在L2P表中记录映射关系。
注意,物理地址与逻辑地址并非一一对应。在上述例子中,逻辑地址4其实对应的是物理地址1。当操作系统向SSD发送指令,要求读取逻辑地址4的数据时,FTL会先从L2P表中得知该数据是在物理地址1上,然后读取数据返回给操作系统。
当逻辑地址0的数据需要更新时,FTL会将新的数据(“A'”)写入新的位置(物理地址13)上,将原先的物理位置(物理地址0)标记为不可用(Invalid),并且在映射表中修改映射关系(逻辑地址0 -> 物理地址13)。
数据更新会导致原先写入的物理地址变得不可用(Invalid),因此需要将这些不可用的 Page 所在的 Block 进行擦除,将无效存储空间释放出来。该过程称为垃圾回收(Garbage Collection)。
GC的核心步骤包括:
确定需要回收的Block。
搬移有效数据(Valid Page)到新的Block。
更新映射关系。
擦除原Block,释放存储空间。
一种常见的GC算法是贪婪算法:优先选择有效数据最少的Block进行回收。
例如,有效Page最少的是Block3,因此选择该Block回收。先读取该Block中的有效数据,即物理地址12。
然后将该数据写入另一个Block中(写入物理地址17),并更新映射关系——逻辑地址15对应的物理地址从12改为17。
这里有个问题,更新映射关系前,如何知道物理地址12对应的逻辑地址是15呢?答案是,需要有一张P2L(Physical to Logical)表,从中获取物理地址12对应的逻辑地址15。
最后,对Block3进行擦除,获得新的可写入空间。
Block的擦写次数过多会变成坏块(GBB,Grown Bad Block)。为了提升SSD整体寿命,需要将块擦除次数均衡到所有块上去——磨损均衡(Wear leveling)。效果如图所示:左边对应未做磨损均衡,红线表示部分Block磨损次数过多,变得不可用;右图对应做过磨损均衡,黄线表示其中磨损次数最多的Block,由于未达到其承受的次数极限,该Block仍然可用。
常见的磨损算法有两种:
动态磨损均衡(Dynamic WL),将热数据写到年轻的Block。
静态磨损均衡(Static WL),将冷数据迁移到老化的Block。
这4个概念的描述如下:
名称 | 描述 |
---|---|
Cold Data | 不经常更新的数据(如操作系统数据、只读文件数据、电影) |
Hot Data | 更新频繁的数据(如txt文件) |
Old Block | 擦写次数Old Block多的块 |
Young Block | 擦写次数少的块 |
SSD中有非常多的设计都是为了加快读写速度,其中一个设计就是MP。
在介绍MP前,需要先介绍下闪存的架构:
1 个Chip有多个Die
1 个Die有多个Plane
1 个Plane有许多Block, 1 个 Die 上并行的多个Block称为Superblock
1 个Block有许多Page,1 个 Die 上并行的多个Page称为Superpage
同一个Die上并行的page共享着相同的 WL 和 Wordline Decoder,因此支持同时对多个Plane上的page进行操作,该操作称为Multi-Plane,简称MP,可加快读写速度。
注意,必须是并行的 page 才可以执行 Multi-Plane 读写。这样会带来一个问题,假如用户需要写入的数据很少,达不到一个super page的大小,直接写入的话无法发挥出MP的优势,如何解决?
答案是,可以将小数据缓存到Page Buffer中,待数据累积到Superpage大小时再写入,以充分利用MP并行能力。
然而,在垃圾回收中,一味追求MP操作,效果可能反而会变差。
假设需要执行垃圾回收时,闪存中有效页与无效page的分布情况如下图所示:
根据贪心算法,优先对无效page最多的Block进行回收,假设仅考虑单个Block的搬运方式,无效page最多的是图中红色框中的BlockA和B。回收时,需要将A 搬到 C、将B搬到D。这种搬运方式,读写次数为:
如果从 super blokc 的视角看,无效page最多的是图中红色框中的Block1。
这种搬运方式,读写次数为:
通过对比发现,第2种回收方式虽然保留了 multi-plane writes,但实际花费了更多的读写次数。因此, Multi-plane operations 虽然可以很大程度上提升SSD的性能,但也需要在FTL中做优秀的设计。
本文仅是我学习FTL的一些理解,更多内容建议阅读:
深入浅出SSD
A Beginners Guide to SSD Firmware
Inside NAND Flash Memories(Chapter 17.4 Flash translation layer)