闪存的工作原理
转载自:https://zhuanlan.zhihu.com/p/35115499闪存价格节节攀升,让三星大赚特赚。其实它的基本原理在1980年代之后基本就没有变化过。它的构成和场效应管(MOSFET)十分类似:它由:源极(Source)、漏极(Drain)、浮动栅(Float Gate)和控制栅(Control Gate)组成。相对场效应管的单栅极结构,闪存是双栅极结构。浮动栅是由氮化物夹在二氧
转载自:https://zhuanlan.zhihu.com/p/35115499
https://zhuanlan.zhihu.com/p/26944064
https://zhuanlan.zhihu.com/p/27328255
闪存价格节节攀升,让三星大赚特赚。其实它的基本原理在1980年代之后基本就没有变化过。它的构成和场效应管(MOSFET)十分类似:
它由:源极(Source)、漏极(Drain)、浮动栅(Float Gate)和控制栅(Control Gate)组成。相对场效应管的单栅极结构,闪存是双栅极结构。浮动栅是由氮化物夹在二氧化硅材料(Insulator)之间构成。
我们的写操作(Program)是这样:
在控制栅加正电压,将电子(带负电)吸入浮动栅。在此后,由于浮动栅上下的二氧化硅材料并不导电,这些电子被囚禁(Trap)在浮动栅之中,出不去了。这样无论今后控制栅电压有否,这个状态都会保持下去,所以闪存可以掉电保存数据。注意写操作完毕后,该闪存单元存储的是0,后面我们将会介绍为什么。
我们的擦除操作(Erase)刚好相反:
在源极加正电压利用浮空栅与漏极之间的隧道效应,将注入到浮空栅的负电荷吸引到源极,排空浮动栅的电子。这时读取的状态是1。
那为什么有电子是0,没电子是1呢?以为读取的时候,需要给控制栅加一个低的读取电压,对于被Program过的闪存单元来说,被囚禁的电子可以抵消该读取电压,造成源极和漏极之间是处于被关闭的状态:
如果是被擦除过的就刚好相反,源极和漏极在控制栅的低电压作用下,处于导通状态:
也就是说通过向控制栅加读取电压,判断漏极-源极之间是否处于导通状态来读取闪存单元的状态,如果被Program过的,就是处于关闭OFF状态,为0;而被Erase过的,就是处于导通状态ON,为1。
理论上来说,闪存可以每个单元来单独擦除和编程。但是为了节省成本,实际上作用在控制栅上的擦除电压是整个块(Block)连接在一起的,这就是为什么擦除要以块为单位了。
为什么闪存会损坏
每次电子在包围浮动栅的二氧化硅上进进出出,都会造成它的老化:
长此以往,浮动栅就不能很好的锁住电子,电子会流失造成漏极-源极之间是否处于导通状态错误,进而数据读取错误。闪存控制器通过校验发现错误后会将其标为不可用,而在OP空间找一块来替代,并在FTL表里改变对应关系。
老狼:杂谈闪存三:FTLzhuanlan.zhihu.com
而 SLC(Single-Level Cell)的省钱版:MLC(Multi-Level Cell) 和 TLC(Triple-Level Cell) 的引入让这个问题更加严重。原来SLC只有ON/OFF两种状态,现在的TLC要有8种状态:
主要靠精确控制浮动栅里面的电子来实现,老化会让这种控制很容易出错。这样就是为什么MLC和TLC相比SLC,生命周期更短的原因:
注意图中的P/E Cycle。
结论
闪存单元的损坏是个不可逆的过程,坏了就是坏了,人死不能复生,节哀顺变吧。几个坏块不会产生多大问题,OP空间完全可以罩得住,问题是只要产生坏块,慢慢坏块会越来越多,写放大也会越来越严重,慢慢的就会产生读写错误,或者速度严重下降。这时我们一定要考虑换块SSD了。
NAND flash的组成
一个典型的Flash芯片由Package, die, plane, block和page组成,如下图:
Package: 也就是chip即Flash芯片,就是我们经常在M.2的SSD上看到的NAND flash颗粒:
Die: 一个NAND颗粒是由一颗或者多颗Die封装在一起而成,这种封装可是平排的,也可以是层叠的。die内部可以通过3D 堆叠技术扩展容量,譬如三星的V-NAND每层容量都有128Gb(16GB),通过3D堆叠技术可以实现最多24层堆叠,这意味着24层堆叠的总容量将达到384GB!就像盖楼房一样:
Die也是可以单独执行命令和返回状态的最小单位。
Plane: 一个die可以包含几个Plane.
Block: 重要的概念,它是擦除操作的最小单位。
Page:也很重要,它是写入动作的最小单位。
FTL
当我们有了块“干净”的Flash,我们第一个想干的事就是写些东西上去,无论我们是写一个byte还是很多东西,必须以page为单位,即写一个byte上去也要写一个page。当我们满意的写了东西上去后,如何修改呢?是不是可以再写一次呢?可惜的是,我们的program操作只能把bit 1改成0,而不能从0改成1. 即我们可以把11110000改成11000000,但不能改成11111111。即有点像逻辑and操作(我们可以通过NAND这个名字联想记忆一下)。那么如何把0改回1呢?这就要靠擦除操作了,但是擦除操作只能在block的上面操作,如果我们把整块block上的所有page都读回RAM,改动后再擦除再写回去(也叫read-modify-write),似乎问题就完美解决了。但是别忘了,我们前文中提到,NAND flash的寿命是由其擦写次数决定的(P/E数 (Program/Erase Count)来衡量的),频繁的擦除慢慢的会产生坏块。那么我们如何才能平衡整块flash的整体擦写次数呢?这就要我们的FTL登场了。
1。FTL原理
FTL简单来说就是系统维护了一个逻辑Block地址(LBA,logical block addresses )和物理Block地址(PBA, physical block addresses)的对应关系, 如图:
有了这层映射关系,我们需要修改时就不需要改动原来的物理块,只需要标记原块为废块,同时找一个没用的新物理块对应到原来的逻辑块上就好了。问题解决了!实际情况比这个稍微复杂些,我们需要解决以下问题:
A. LBA和PBA究竟是对应page还是block?
B. 如何做到寿命均衡?
C. 废块何时回收?
D. 这个逻辑对应表存储到哪里?
2。LBA/PBA的颗粒度问题
如果我们把LBA和PBA都设置成page大小,这也叫做page-level mapping,这和我们写入颗粒一致,很灵活。但这么小的粒度会带来一个问题:逻辑对应表太大!想象一下,我们有个64GB的Die,每个page只有4KB,我们的对应表需要64*1024*1024 * 4 /4 = 64MB!这个绝对不能接受。那么按照block,也就是block-level mapping呢? 会不会好些呢?至少占用空间好了很多,但是因为写入时不清楚page情况,往往要整块擦除,效能会大大下降。有没有更好的办法呢?实际使用中常用的是log-block mapping,它从我们现代的log文件系统中学到经验,也充分利用了page和block的不同特性。它比较复杂,我们这里按下不表。
3。如何做到寿命均衡(Wear Levelling)
LBA/PBA的映射本身会对寿命均衡产生正面影响。就如我们SD卡上的FAT文件系统,文件分配表会被经常修改,但由于修改的是逻辑块,我们可以让每次物理块不同而避免经常擦写相同的物理块,这本身就保证不会有物理块被经常擦写。但是有一种情况它没有办法处理,即冷的数据块(cold block),它们被写入后没有更改,就一直占据某些物理块,而这些物理块寿命还很长,而别的热的块却在飞速损耗中。这种情况怎么办呢?我们只有在合适的时机帮它们换个位置了,如何选择这个时机很重要,而且这个搬家动作本身也会损耗寿命本身。这些策略也是各个FTL算法的精华了。
4。垃圾回收
废块需要找时机回收,这就需要垃圾回收(GC,Garbage Collection)机制。
现在到处都会碰到GC,各种高级语言都在炫耀自己有GC,不像C++/C那样要手动回收内存。这里的GC是指回收废块,但是时机非常重要,谁都不希望看到一个存盘后,SSD硬盘固件发现没有干净的块可用,开始整盘GC,就像开始了一个没有进度条的磁盘整理,系统被完全卡死了。聪明的固件往往未雨绸缪,在我们不知不觉下在后台悄悄做垃圾回收,不少固件还同时进行Wear Levelling。
5。LBA/PBA表存储在哪里
这个表随时可以变化,我们把它存储在哪里呢?是不是也找个page存起来呢?事实上,在大部分的NAND Flash里,还有些空闲块,我们叫它OP(Over Provisioning)。如下图:
这些空闲的块可以极大的帮助我们改善NAND flash的性能,它可以:
A. 坏块处理。发现坏块,这些后备的可以立刻顶上,因为有映射机制,上层软件完全感受不到。
B. 存储LBA/PBA表
C. 给GC和Wear Levelling留下极大的腾挪空间。
D . 减少写入放大(Write Amplification)
事实上,现在几乎所有主流SSD等NAND die上都有OP。譬如我们拿到标称容量240GB的SSD,实际空间可能有256GB甚至更高(一般>7.37%),只不过这些多余的空间我们用不到,感受不到,它完全被SSD固件藏做私用而已。
尾声
现在能生产NAND芯片的厂家在Wikipedia上能查出11家,而能生产主控芯片和固件的就四家。他们各自的绝活都在FTL中的各种调优上,再加上Trim等等特性,这也就决定了SSD硬盘性能的好坏。
Trim
OS在删除一个文件时并不是把内容写0,而是把索引和文件存储空间标记为作废。这也是一些所谓安全删除软件有所作为之时(如何优雅的删除你的"秘密"文件 - 知乎专栏)。但是SSD主控并不知道这个情况,它还认为文件存储空间是有用的数据,在写放大和GC的过程中不停的搬来搬去,造成性能和寿命的下降。我们举个例子,如下图:
1. 以OS的观点看是第一栏,第一列有四个文件,第二列删掉了文件C,第三列加入了文件E。
2. 以OS的LBA的观点看是第二列,C文件被删掉后,E文件被直接覆盖到了C文件的位置。
3. 以主控的PBA观点看是第三列,C文件被删掉后,主控并不知道,它还认为和第一列一样C1/C2是有价值的内容,在写放大和GC的时候被搬动。直到第三列OS在LBA原位置写了E文件后,主控才知道C1/C2是废物,才被标记为GC(垃圾收集)。
这种OS和固件的脱节在Trim命令引入后得到改善,OS在C文件被删除后会利用Trim命令告诉主控:“C1/C2没用了,你看着办吧。”,主控可以立刻标记它们为废块,不再搬动,并在合适的时机进行垃圾收集(GC)。这样极大的减小了写放大和提高了SSD的寿命。
Trim是好,但是要OS和主控都支持才行。那么如何打开Trim呢?
1. Windows在Win7之后就支持了Trim。
2. OS X在10.6.8之后支持了Trim。
3. 我们的手机OS,Android在4.3之后才支持Trim。
不同的SSD厂商支持Trim的时间不同,如果你是在最近三年买的SSD,那么你的SSD很可能是支持Trim的,具体请阅读SSD说明。
结论
Trim并不能消灭手机或者SSD的写放大,但是能部分减缓它。还有些别的优化的方法,这些方法是不同的SSD厂商的独家绝活。要用好它们,你最好安装各个厂家的Optimizer工具,并立刻使用它们,对于手机来说,只有选择>4.3的安卓,并保证剩余空间>25%。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)