嵌入式Linux中文站

基于nand flash的文件系统的整理


原文:http://blog.csdn.net/w746805370/article/details/50946368
一、            Nandflash简介

基本概念:flash芯片、block、page、附加页

1.1结构

Flash芯片的擦除以块为单位写以页为单位。在每个flash芯片中包括非常多的块,同款芯片上每个块的大小相同(2MB、4MB..),在每个块上包含多个页,每个页大小相同。在每个页面后都跟随着一个附加页,用来对对应页面进行标记或者对页上的数据进行校验,页面通常的大小为2Kb+64byte、512byte+32byte、1024byte+64byte等。结构如图1.1所示:

 

图1.1,nand flash结构示意图

1.2   特点(对于flash的研究主要是针对其特点优化其性能或者克服其缺点)

1.        Nand flash不是通常意义上的块设备,块设备的特点是可以对数据块进行读、写操作(如磁盘,文件系统等),但是对于Nand flash来说有三种操作分别是:读、写、擦除。只有对已擦除的块才能进行写操作。所以为了使其兼容传统的硬件和系统,需要对其进行特殊处理;

2.        当一个闪存处在干净状态时(被擦除过,但是还没有写操作发生),这块flash上的每一位(bit)都是逻辑1;

3.         nand flash不可以片上执行,但是存储密度大,因此常作为存储介质使用;

4.         Nand flash是按位寻址的,意味着可以从一块闪存的任意偏移地址读数据;

5.         闪存的使用寿命是有限的,具体来说,闪存的使用寿命是由擦除块的最大可擦除次数来决定的。超过了最大可擦除次数,这个擦除块就成为坏块(bad block)了。因此要避免某个擦除块被过度使用,以至于先于其他擦除块变成坏块,应该在尽量少影响性能的前提下,使擦写操作均匀分布在每个擦除块上,叫做损耗均衡(wear leveling)。

 

二、文件系统简介

文件系统是对于文件和存储空间的组织和管理,并对内核提供调用接口。主要是对数据结构的设计。在一定程度上类似数据库ACID(原子性、一致性、隔离性、持久性)的设计理念。

2.1文件系统结构

传统文件系统ext2与基于flash设备的文件系统在系统中的位置对比图。

 

图2.1各文件系统对比图

2.2 目前成熟的可以使用在非易失存储器上的典型的文件系统

为了在掉电或者系统崩溃情况数据的一致性,很多文件系统都增加了日志的功能。日志文件系统(journaling file system)一般执行步骤如下:

1.        预备:当系统要写入一个文件时,会现在日志记录块中记录某个文件准备要写入的信息;

2.        实际写入:开始写入文件的权限与数据;开始更新meta data的数据;

3.        结束:完成数据与meta data的更新后,在日志记录块中完成该文件的记录

在日志系统的帮助下,万一的记录过程中发生了问题,那么系统只需要检查日志记录块就可以知道哪个文件发生了问题,针对该问题做一致性检查即可,不必对整个文件系统做检查,从而达到快速修复文件系统的目的。

 

2.2.1  Ext2\ext3\ext4文件系统

Ext2可以通过FTL实现对flash的支持,FTL可以将闪存flash模拟成磁盘结构,从而实现对基于磁盘的文件系统的支持,但是效率比较低。Ext2文件系统结构如图2.2.1.1所示

 

图2.2.1.1 ext2文件系统结构图

各名词解释如下:

1.        超级块(super block):记录此文件系统的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式与相关信息;

2.        i节点(inode):记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的block号码;

3.        block:实际记录文件的内容,若文件太大时会占用多个block。

由于每个inode与block都有编号,而每个文件都会占用一个inode,inode内则有文件数据放置的block号码。Inode索引结构如图2.2.1.2所示。

 

图2.2.1.2 inode结构示意图

在ext2文件系统的基础上上,为了保证数据的一致性ext3文件系统增加了日志功能。

在ext3文件系统的基础上ext4文件系统增加了对大文件(T单位级的文件)的支持,另外对于每个目录下的文件个数没有了限制。

EXT2文件系统在flash上使用的弊端:

不是直接对flash设备进行使用,在很多方面不兼容,比如没有针对flash的特点以及弊端实现擦除、垃圾回收以及损耗均衡等操作的处理,全部凭借着下层的黑盒FTL来实现这些功能,这些都不利于研究和做实验。

 

2.2.2  JFFS2文件系统(链表结构,典型的日志文件系统)

JFFS2文件系统以节点方式来管理flash设备上的所有文件,目录也被当作一种普通的文件来管理。有dirent和inode两种节点类型,所有的信息分散的存储与各个节点之中。Dirent形成整个文件系统的层次结构,inode管理构成文件的所有数据(普通节点和meta data节点)。图2.2.2表示flash中节点的逻辑分布,而物理上所有的节点各自独立的散布在flash设备上,其位置由写入节点时flash空闲位置决定。

 

图2.2.2 flash中节点的逻辑分布图

在系统初始化的时候挂载JFFS2文件系统,首先扫描整个flash设备,然后建立起文件系统在内存中的映像。系统运行期间,就利用这些在内存中的文件信息进行各种文件操作。JFFS2为每一个flash设备维护一个装载点和一个超级块结构,这两个数据结构含有整个flash设备的信息。系统中维护了几个重要的链表,这几个链表构成了更个文件系统的骨架。

1.        物理块信息链表:在超级块中,系统维护一个物理块信息链表,其中每一个节点包含一个物理块的信息,包括该块在闪存中的偏移位置、使用情况,及所有存于这个块中的节点的链表等信息。通过这个节点链表,我们可以找到存在于flash设备上面的任何一个节点。

2.        Inode cache链表:在超级快中,系统维护一个icache链表,每个icache代表一个文件,包括普通文件和目录文件,由一个ino号所标识。所有属于同一个文件的节点信息由指针形成链表,挂接在这个icache上,这样对文件任何一个节点的操作都可通过这个链表定位。

3.        Inode链表:在系统运行期间,系统中还维护着一个打开文件的inode链,在inode中,所有属于这个文件的节点按照数据在文件中的逻辑偏移形成数据片链表,对文件的读写操作就是通过这个链表进行的。

根据文件名查找文件inode的结构如图

 

图2.2.3根据文件名查找文件inode

另外JFFS2文件系统是基于MTD设备而设计的,实现了擦除、垃圾回收、损耗均衡等机制。

1.        垃圾回收:循环使用块表,在空间不够或者内核专门激活的时候调用垃圾回收机制,产生足够多的可用空间。

2.        损耗均衡:所有节点由版本号(无符号32位,在整个flash的生命周期内不重置)控制,新写入的数据有最高的版本号,由此尽量保证所有块读写擦除次数相等。

3.        数据保护:对数据进行周期的CRC冗余校验,但是只能给出一个错误的信号,并不能纠错误。

JFFS2文件系统的弊端:

1.        损耗均衡策略产生了不必要的擦除,加速了损耗;

2.        由于要扫描整个flash空间的块并加载所有的日志到内存中(扫描三次),严重影响了加载文件系统的性能;

3.        在空间不够的时候回收机制激活产生大量可用空间,这个过程会浪费掉很多时间;

4.        垃圾回收机制的阈值是凭经验得出来的,没有明确的理论支持,另外在垃圾回收的时候必须预留有足够的空间,否则系统将不能删除任何东西;

5.        数据压缩功能和垃圾回收机制相互冲突。

 

2.2.3  UBIFS文件系统(Unsorted Block Images File System)

设计目的:UBIFS就是为了克服JFFS2文件系统的缺点而设计的。UBIFS建立在UBI volume之上(Unsorted Block Images),涉及到三个子系统,结构如图2.1所示。

 

1.        MTD子系统,提供对flash芯片的访问接口,MTD子系统提供了MTDdevice的概念,可以被认为是裸的flash(raw flash,区别于带有FTL的flash或者SSD)。

2.        UBI subsystem,为flashdevice提供了wear-leaving和volume management功能。UBI工作在MTD设备之上,提供了UBI volume;UBI是MTD设备的高层表示,对上层屏蔽了一些直接使用MTD设备需要处理的问题,比如wear-leaving以及坏块管理。结构如图2.2.4所示(LEB逻辑块,PEB物理块)

 

图2.2.4 UBI与MTD设备映射图

3.        UBIFS文件系统,工作在UBI之上,其中坏块管理,磨损均衡,错误预测等功能有UBI子系统完成,UBIFS不予关心。

UBIFS层位于通用块层和UBI层之间,通用块层的核心对象是inode和superblock,UBI层的核心对象是LEB,写操作就是要根据inode,进行UBIFS层的处理,找到UBI层的LEB,并把数据写到存储介质上。UBIFS主要用了B+树的数据结构,对设备空间爱你的划分如下,其中log、LPT、orphan、main区的具体大小取决于flash的物理大小。

 

表2.1

·  super block area:super block 使用LEB0,其描述的文件系统基本信息,如index tree fanout, default compression type (zlib or LZO), log areasize等等。由格式化工具在格式化时写入,对ubifs只读。

·  master node area:master area使用LEB1和LEB2,两个LEB相互备份。这个是为了恢复着想,因为有两种情况会导致主节点损坏或丢失。第一种情况就是当主节点正在被写入的时候突然断电;第二种情况是可能是flash介质自身损坏。有了两个备份的LEB,就可以根据情况去恢复。master area保存着commit number、root index lnum和offset、start log lnum和offset、start index lnum和offset、root lpt lnum 等信息,每次提交时会更新master area上这些信息。

·  log area:上面我们提到了UBIFS中这样的树状结构是保存在flash中,那么就带来了一个问题,每次更新文件,相应的文件信息和数据都会发生变化,那么这颗树种的结点也会发生变化。而我们知道NANDFLASH的特点,每次重新写入之前必须擦除,可见这样频繁的操作带来的是效率的低下。为了降低片上树结点频繁的更新,UBIFS中创建了log区,按日志形式记录树节点的位置信息leb:offs修改,然后一次提交到main区上,这样就降低了更新的频率。存于log的节点类型为UBIFS_REF_NODE,其flash的表示为ubifs_ref_node,内存的表示为ubifs_bud,主要记录node的位置信息leb:offs。ubifs_bud按RB树组织,以lnum为key。

·  mount时会扫描log区,读出bud并重新索引。这个过程叫回放(replay)。umount时会把bud提交到log区。

·  lpt area:LPT主要用于对LEB的分配、回收、状态查询(free、dirty、index、etc.)。

· 我们上面提到了logarea的目的,就是降低数据的更新频率。但是数据如何更新呢?也就是说,这些新添加的数据写往何处?所以必须对flash中每一个块的空间使用情况有一个了解,这就是LPT(LEB properties tree)的目的。LPT也是B+树,单比index tree小很多,其主要包含三个重要的参数:free space、dirty space 和index or data。mount时,判断如果lpt_sz(nnode, pnode所占大小)大于一个LEB,自动使能big_lpt 模式和垃圾回收功能。LPT区只在提交时更新。

·  orphan area:link数为0的inode节点,这个inode号被添加到一个orphan RB-tree

· commit时,孤儿树中新孤儿被写到orphan area, mount时会扫描orphan区,删除orphan节点。

· main area:文件系统的数据和索引节点,作为B+树的index node存储在main区。

 

第二部分总结:

通过对现有的文件系统资料和源码的研究,让我清楚了什么是文件系统和文件系统的运行机理。加深了对flash设备特点的了解,并且发现和总结了现有文件系统的优点以及有待于补足的缺陷部分,为我们自己文件系统的研究积累宝贵的经验,指明了阅读文献、论文的方向。

 

三、目前的研究方向

对于nand flash来说目前有两个总的研究方向,其一是将其作为代替磁盘而存在的存储器(比如固态硬盘SSD),其二是和DRAM结合成为非易失性存储器NVRAM(目的是为DRAM添加数据非易失的存储特性从而来代替DRAM)。

3.1硬件层

3.1.1 FTL(flash translation layer)

flash翻译层(作用:地址转换、垃圾回收、损耗均衡,不开源),针对flash的一些特性进行操作,对上屏蔽掉flash的操作细节,将flash模拟成一个具有512字节扇区的标准块设备(block device),使得传统的文件系统也可以像工作在普通块设备上一样正常的,使用如图3.1.1.1所示。

 

图3.1.1.1通常的FTL映射

FTL devices是一个黑盒。FTL算法是vendor公司的商业机密。有很多人在几年前就对此作了研究。

对于为了纯粹代替磁盘的flash存储器来说,与传统的磁盘在系统中的区别如下图所示: 

                                                                                                                    

 

图3.1.1.2(a)通常的块设备处理示意图              图3.1.1.2(b)flash设备使用示意图

注:图3.1.1.2(b)中FTL/MTD相当于图3.1.1.2(a)中的块设备驱动程序的位置,其余位置相同。

MTD(memorytechnology device)存储技术设备,开源,已加入到linux内核中,模块为mtdblock,在基于通常的FTL机制的实现上又加入了一些优化,只有当文件系统的写请求超过了一个擦写块的边界的时候,他才执行闪存的擦除、写回操作。另外,MTD还理解上层文件系统的语义,从而实现垃圾回收(Garbage Collection)。

 

3.1.2         NVRAM(DRAM+非易失性存储器)设计:

设计时候要注意的问题:

·   性能:因为Nand flash的读写速度与DRAM相差千倍,如何协调两者的速度不一致性,是设计NVRAM首先要考虑的问题;

·   能耗:nand flash读取数据的时候基本上没有什么能耗,但是写数据的时候需要能耗很高,所以设计NVRAM的时候要尽可能的避免过多的写操作;

·  损耗:在第一节nand flash的特点中已经介绍,闪存的使用寿命是有限的,具体来说,闪存的使用寿命是由擦除块的最大可擦除次数来决定的。超过了最大可擦除次数,这个擦除块就成为坏块(bad block)了。作为主存的NVRAM的读写次数数量级是很大的,如果没有特别的限制,在几分钟内就会有坏块产生,所以在设计的时候要特别注意损耗均衡机制的设计。

3.1.2.1   DRAM与非易失性存储器平行设计(重点在于控制器的设计)

重新设计文件系统的数据结构,所有的数据都会有一个标志位,标识该数据是系统元数据还是用户数据,在内存中控制器通过辨别标志位的方式将数据存储于DRAM或者非易失存储器中。NVRAM结构设计如图3.2.1所示。

 

图3.1.2 平行的NVRAM设计图

区分用户数据(粒度较大,使用较不频繁)和系统数据(使用频繁),通过控制器分别进行存储、迁移调用。另外Nand flash作为NVRAM中的非易失性存储器使用的时候,因为其不能片上执行,它的存在只是为了实现NVRAM的非易失性。故而在程序执行的时候还需要将数据从nand flash上迁移到DRAM上,DRAM上的重要数据要周期性的的写入到nand flash上从而实现非易失性。

3.1.2.2   DRAM与非易失性存储器垂直设计

在垂直设计结构中,DRAM相当于一个缓存,用来匹配nandflash与CPU的速度不兼容问题,整体作为内存使用,设计类似于现阶段的内存与高缓结构。如结构图3.2.2所示:

 

 

图3.1.3垂直型NVRAM结构示意图

3.2系统层

3.2.1文件组织方法(数据结构的设计)

         对文件系统的设计主要是对数据结构的设计,常见的用于文件系统的数据结构有:B+树、RB树、优先队列、链表、哈希表、数组。目前的对文件系统数据结构研究方向也主要是在此基础上的改进。对于树的操作的研究主要集中在查找、插入、删除、更新四种操作上。

3.2.1.1   NV-Tree(基于B+树的改进)

NV-Tree主要是对保证数据一致性的改进。树的结构如图3.2.1.1所示

 

图3.2.1.1 NV-Tree树的结构示意图

主要包括三种类型的节点,分别为:Leafnodes(叶子节点)为critical data(临界数据);internal nodes(内部节点)记录reconstructable data(重构数据);Parent Leaf Nodes。三种节点结构如图3.2.1.2所示。

 

图3.2.1.2NV-Tree树节点结构示意图

在B+树中,如果一个节点要分裂的话,新的节点要被完全重写,但是在NV-tree中只需要对叶子节点进行操作,节省了大量的操作。所有的数据都存储于LNs中每个LNS可以被存储于PLNs中的指针所访问。并且所有的Ins/PLNs一旦被创建就位置固定下来不能再被改变,并被一个node id唯一标识(root node 的id为0),node id也可以被称之为以root为根的节点的偏移量。从root可以根据二分查找或者hash表的方式找到任意节点。

对于NV-tree的插入、删除、更新操作如图3.2.1.3所示:

 

图3.2.1.3NV-Tree的插入、删除、更新操作示意图

NV-TREE叶子节点分裂示意图如图3.2.1.4所示:

 

图3.2.1.4 NV-tree叶子节点分裂示意图

3.2.1.2   另外还有很多比如CDDS-tree,u-tree,u+-tree等树结构,不再赘述。

 

3.2.2对存储器的利用:减少能耗、损耗均衡、垃圾回收、碎片整理

减少能耗:主要是减少写操作,可以将使用频繁的系统数据和不频繁的用户数据进行区分存储,比如将DRAM中的数据分别放入热冷数据链中,用相应的算法判断是否有必要写到闪存中,以此来减少写操作。

损耗均衡:目前主要有两种方式,其一,将所有的物理块使用次数计数(记录的次数将伴随flash的整个生命周期),每次写之前查看记录的次数,尽量保证每个块使用次数相等;其二,使用UBI的方式,将物理块映射成逻辑块,无序的映射,尽量保证每个物理块的使用次数相等。

垃圾回收:将脏物理块擦除以便重新写入,在脏块中有干净数据的话,需要将干净数据拷贝到新的空闲块中。

碎片整理:因为flash写的最小单位是页,所以小数据的写入就会产生大量的碎片空间,导致大量的空间浪费,进而有加剧了flash的损耗速度,因此必须有碎片整理机制,将碎片化的数据整块写入,或者结合垃圾回收机制将碎片数据整合后放入整块中。

 

3.2.3数据写入方式:write-back(msync)、write-through(fsync)

         对flash存储器的数据写入只要有两种方式,一种是写回方式,另外一种是写透的方式。

在DRAM中有块高速缓存区,为此减少了DRAM对flash的访问。写回的方式是系统将要写的数据放入块高速缓存中,并标记脏位,一段时间后同步程序自动将数据写入flash中。写透的方式是系统不经过缓存之间将数据写入存储器中。

 

3.2.4数据安全问题:数据一致性问题(掉电保护,系统崩溃),数据校验(CRC\ECC),日志与非日志

         所有关于文件系统的研究都必须要考虑这几方面的内容。

 

3.2.5存储的数据是否压缩

数据压缩存储可以支持存储器存储更大容量的数据,但是数据压缩常常与垃圾回收相互矛盾,如何均衡两者利弊也是一个研究点。

 

3.3应用层

用户数据的一致性问题

         目前大多数文件系统的研究都是关于系统数据一致性,系统数据的安全性等问题。而且大多数文件系统已经具备了掉电、系统崩溃等情况发生时候数据恢复的能力,但是很少有关于用户数据安全性的研究,而是由用户程序自己完成在程序崩溃或者其他突发情况下的数据恢复。

 

四、学习过程中发现的问题

1.在研究了很多资料后,发现虽然目前大多数文件系统还都是基于非易失存储器的文件系统,也有专门的基于DRAM的文件系统(比如ramfs),但是目前还没有发现既可以管理DRAM又可以管理非易失存储器的文件系统。因为大多都是程序都是模块化的设计,两者的存储机制不一样,所以分开管理更加容易。

2.文件系统的模块化设计使得各个文件系统以各自为单位,共同工作在虚拟文件系统(VFS)之下,各文件系统之间被完全隔离没有通信。基于此,可否分别设计出基于DRAM的文件系统和基于闪存的文件系统,并让其相互通信。

本文永久更新链接:http://embeddedlinux.org.cn/emb-linux/file-system/201711/29-7837.html



分享:

评论