大家好,我是五月。
前言
FTL(Flash Translation Layer),即闪存转换层,是各种存储设备的核心算法,作用是将Host传下来的逻辑地址转换成物理地址,也就是映射。
地址映射是FTL最原始最基本的功能。
那么FTL究竟是怎么样完成映射工作的?
映射种类
首先要知道,映射种类有仨:
1. 块映射
2. 页映射
3. 混合映射(块映射+页映射)
块映射
以Block为映射单位,一个逻辑块可以映射到任何的物理块上,所以块内每一页的偏移不变。
还需要映射表来记录逻辑块和物理块之间的映射关系。
优点:因为映射表只需要块的映射,所以映射表所占空间小。
缺点:性能差。如果用户要操作一个逻辑页的话,就需要把整个块的数据读取出来,再修改逻辑页,再写入flash当中,所以小尺寸数据写性能极差。
页映射
以page为映射粒度,一个逻辑页可以映射到任何的物理页上,所以块内每一页的偏移变化多端。
需要映射表来记录每一逻辑页与物理页之间的映射关系。
优点:用户可随时操作某一逻辑页,直接将数据写进对应物理页,方便快捷,性能极好。
缺点:由于每一逻辑页与物理页都有一张映射表,并且页的数量远远要比块的数量多得多,所以映射表所占空间极大。
混合映射
混合映射是块映射和页映射的混合产物。
一个逻辑块可以映射到任何的物理块上,块内采用页映射方式,块内逻辑页可以映射到对应物理块内任何物理页上。
所以在性能和所占空间都介于块映射和页映射之间。
以下是不同映射之间的比较:
映射原理
Host是通过发送逻辑地址 LBA 来访问Flash的,每一个LBA大小为 1Sec。
每一个Sec大小各有不同,有512B、4KB、8KB,大部分情况下都是512B,业内常称为一包数据。
写过程
Flash是以page为单位进行写的,所以Host发送的 LAB+数据并不会立马就写进入,而是会先在Dbuf缓存起来,直到凑成了1page的数据量,才会写进Flash中。
用户每写入1page数据,FTL会先去找映射,看看LBA有没有对应的映射关系,如果没有找到,就会找一个物理页吧用户数据写入,同时新建一条映射。
那么,用户逻辑地址和物理地址的一条映射就生成了。
每写入一个逻辑页,就会有一条映射表产生或者更新。
读过程
用户读取某一个区域,发送LBA进行访问时,FTL就会先在映射表池里找呀找,找到与LBA对应的映射表,FTL就知道要在Flash的哪个物理页把数据读出来了。
如果读过程没有找到映射表,那么读取过程失败。
映射表位置
DRAM
大多数存储设备都有板载DRAM,映射表就能存储在DRAM上
作用:可以快速访问映射表,快速读写
缺点:随着映射表越来越多,所占DRAM就会越来越大,提高了成本和功耗。
Flash
后来的主流是映射表大部分被存在于Flash中,当下要用的小部分映射表存于DRAM中。
作用:降低成本和功耗,还可以避免掉电带来的映射信息损失,另外Flash空间很大,映射表想放多少放多少。
Host发送LBA的时候,FTL会先在DRAM中寻找,如果没有找到对应的映射表,就会去Flash中读取映射表,再根据映射关系操作对应的物理页。
缺点:需要读取两次Flash,一次映射表,一次用户数据,底层带宽减小了,对于随机操作来说,就显得效率低了一点。
映射表更新
随着映射表的增加、删除、覆盖,到了某个时刻就要把映射表写进Flash保存起来,避免掉电时发生大量映射表丢失。
时不时将映射表写进Flash,就算发生了突然的异常掉电,丢失的也只是小部分映关系,后面还能通过重建映射表恢复回来。
映射表的写入时刻
1. 新生的映射表数量积累到一定的阈值
2. 用户写入的数据量积累到一定的阈值
3. 空闲闪存块的剩余数量达到一定的阈值
写入策略
1. 全部更新
将所有的映射表,无论是新产生的还是原先就有的,全部一股脑写入Flash中。
优点:固件实现简单,不用去考虑哪些映射表是新的,哪些是原本就有的。
缺点:写入数据量多,影响性能和延时,还会增加写入放大。
2. 增量更新
只把新产生的映射表写入Flash中。
优点:新增写入的数据量少,性能好,时效高。
缺点:固件实现复杂,还得区分那么那么些是新增的映射表,哪些是被覆盖的。
选择哪种写入决策,应根据硬件架构,结合实际情况考虑。
好了,这次先写到这儿,祝各位生活愉快。