朱绍英,查启鹏
(中国电子科技集团公司第三十二研究所,上海200233)
基于嵌入式Linux的YAFFS2文件系统研究与改进
朱绍英,查启鹏
(中国电子科技集团公司第三十二研究所,上海200233)
YAFFS2文件系统是针对NAND Flash按块擦写特点设计的一种专用Flash文件系统,其存在加载时间长和NAND Flash专用的局限性。为此,从Flash存储器管理和文件管理2个方面分析该系统的设计原理及特性,提出一种新的文件系统信息存储方式,并从文件系统初始化、垃圾回收、断电保护等方面对YAFFS2文件系统进行改进,减少加载时间,使之能应用于多种Flash存储器。测试结果表明,与原系统相比,改进系统的安装时间减少25%,并可实现Flash各存储扇区的均衡使用。
YAFFS2文件系统;NAND存储器;嵌入式Linux系统;垃圾回收策略;损耗平衡
Flash存储器由于具有存储容量大、掉电数据不丢失以及可多次擦写等许多优点而被广泛应用于各类电子产品中,其存储特性决定了已有的磁盘文件系统不能直接用于Flash存储器,而必须采用专用的Flash文件系统。Flash文件系统除了要满足一般文件系统的基本要求外,还要根据其自身的一些特性实现对Flash的有效管理。如广泛应用于NOR Flash的JFSS2(Journalling Flash File System)专用文件系统,而有些Flash存储器如MMC卡、SD卡,由于内嵌了各自的FTL(Flash Translation Layer)固件,使得传统的磁盘文件系统可以直接使用。YAFFS2文件系统是A leph One公司针对NAND Flash的特点而设计的一种专用Flash文件系统[1]。它主要是通过NAND Flash每页的OOB(Out of Band)区存储文件系统信息而实现的,具有效率高、占用资源较少等特点[2]。本文分析YAFFS2文件系统的基本工作原理,包括存储器管理和文件管理,针对其加载时间随文件系统分区增大而线性增大和仅限于NAND Flash的局限性,提出一种新的文件系统信息存储方式,避免使用OOB区,并改进文件系统初始化时的扫描方式以及垃圾回收和掉电保护机制,实现在NAND Flash、MMC卡和NOR Flash等Flash存储器上搭建YAFFS2文件系统的目的。
Linux下的文件系统一般设计一个文件系统信息组成的“超级块”,存放在存储器的特定位置,其中包含了存储器空间大小、存储器使用情况和各个文件的存放信息等,并在文件系统安装时被读入以建立VFS(Virtual File System)层的super_block结构实例[3-4]。然而,YAFFS2文件系统中存储器上并没有类似的超级信息块,在加载文件分区时,通过扫描存储分区来得到相应的文件系统信息并建立super_ block结构实例,包括一些其他的信息,例如文件节点等。对于用户,文件系统就是要实现按名字存取文件,以及文件和目录的一些的管理操作,如创建、删除、读写等[5-6]。下面分别从存储器管理和文件管理与来具体分析YAFFS2文件系统的设计原理。
2.1 NAND存储器管理
YAFFS2文件系统以扇区为单位在NAND Flash存储数据,即NAND Flash的页,页的大小主要有512 Byte,2 KB和4 KB等。若页大小为2 KB,则每页有64 Byte大小的OOB区,而所有页的分配与读写是以块为单位进行管理的,YAFFS2文件系统通过将存储器的每个存储块分成为各种不同的状态进行组织管理,实现中使用共用体结构yaffs_ BlockState来标识,分别有初始、扫描、空闲、分配中、满、脏6种状态[7]。其中扫描状态是指在加载文件系统时,正在读该存储块的数据,并对其数据进行分析处理,在整个文件系统分区的所有存储块的数据处理完之后,这些状态的存储块分别会设置最后的使用状态;当存储块中所有的扇区都被使用时,会被标记为满或者直接标记为脏状态,后者是指存储块中所有扇区的数据都被标记为无效数据,必须将这个存储块擦除为空状态,加入到可分配列表中,供后面分配使用;在任何时刻,一个文件系统分区中有且只有一个存储块被标记为分配状态,在写文件或者垃圾回收时,先找到当前分配状态的存储块,然后顺序分配一个扇区进行写入,当该存储的所有扇区都写完后,就要再在空闲状态列表中找到一个块作为当前分配块。
为了更有效地使用Flash的各个存储块,实现中使用yaffs_Block Info结构来详细地描述每个块的使用情况:
在上述结构中,sequenceNum是记录在该分区内此块的使用顺序,在文件系统分区中是全局递增的,主要在垃圾回收算法中用于判断数据有效性;deletion表示该块内被删除的页数;needsRetiring指使用过程中读写或者擦除出错,不能继续被读写和使用。在YAFFS2文件系统中,NAND Flash每页的OOB区域用来存储文件和页使用信息,如文件系统结构信息包括页号、文件号、有效数据字节数等,以及该页全部数据的ECC校验码。比如页大小为2 KB时,其具体每个页的数据存储布局如表1所示。
表1 数据存储格式
2.2 文件表示与管理
从使用者的角度看,文件系统就是要实现文件的按名存取,即文件管理,其关键是文件的表示、组织和文件的索引、定位。文件的表示主要包括用于描述每个文件的各种属性数据以及这些数据如何在设备上存储,而文件的定位主要涉及到如何索引存储该文件数据的所有页。
在具体文件系统的实现中,文件的表示一般包括静态存储和动态操作的数据,实现对文件的组织管理,其中在设备上静态存储的数据主要有3种:文件描述信息,包括名字、数据长度、存储地址、创建者、访问权限、使用情况等;文件内容本身的数据;存储空闲空间统计信息。而在内存中动态操作的数据管理信息主要有内存文件描述信息、内存文件系统分区信息等,在内存中建立这些数据信息是为了提高文件系统运行的效率和文件系统的各种性能。Linux操作系统在上层统一在虚拟文件系统VFS实现统一的接口,各个具体文件系统实现VFS定义的各个接口。在VFS层用struct inode统一描述各种文件系统中的文件,该结构定义了各种文件的一些共同属性信息,还包括了各种具体文件系统用于描述文件的各自私有的属性信息,如EXT4文件系统的ext4_inode结构。
在YAFFS2文件系统中,Flash存储器上并没有定义和存储这类信息,它是通过在文件系统加载时扫描文件系统分区,然后为设备上每个文件分别建立文件描述信息,即yaffs_Object结构。在YAFFS2文件系统中,每个文件都用一个页来存储所有属性信息,如名字、文件号、大小、父目录的文件号、创建时间和用户等,其描述结构为yaffs_ObjectHeader,该对象主要是根据文件头数据而创建的,当扫描某个页时,先读取该页的OOB的标志,从而判断该页数据是一个文件头,如果是,就在内存中新建一个文件对象,再在后面的读取过程中将该文件数据所在页号记录到其variant域中,后面定位文件数据时会使用该对象[8]。NAND Flash每页的OOB中存放的文件定位信息是用yaffs_PackdTags2Part结构描述的,其具体组织如下:
其中,objectId用于唯一标识该文件的文件号;chunKId表示文件的数据页号。从这2个ID就知道文件系统分区中各个页与各个文件的一一对应关系。YAFFS2文件系统中定义了文件树来记录各个文件的各个设备页号,其文件树的结构如图1所示。
图1 YAFFS2文件树
文件树的最底层存放属于该文件的所有设备页号,是16维数组,而其他层都是8维,存放下层的指针,每个文件需要的层数根据文件所占的页数确定。例如:若文件的数据扇区数少于16×8个,则总共只需2层便可。其结构定义如下:
在进行文件数据读写时,根据文件名字找到文件对象yaffs_Object,然后得到文件树结构域variant,这样就知道了该文件数据存放在Flash上的所有页号,然后调用底层驱动读写页内的数据,在写文件时,还要将新的扇区号更新到文件树结构中。
YAFFS2是针对NAND Flash专门设计的文件系统,它必须使用NAND Flash每页的OOB区存储文件系统信息,而NOR Flash、MMC卡等Flash存储器上并没有OOB区,所以,YAFFS2不能在NOR Flash等上使用OOB区实现存储器管理和文件管理;其次YAFFS2文件系统加载过程中需要读文件系统分区每页的OOB数据,会导致加载时间随NAND变大而加长。
针对这2个问题,本文设计了一种新的文件节点存储方式,将文件系统信息存放到Flash页内,使得文件系统能正常运行于NAND Flash,NOR Flash, MMC卡等Flash存储器。
3.1 文件属性信息的存储方式
如前文所述,YAFFS2文件系统信息存放在NAND Flash上的OOB区域,其描述结构为yaffs_ PackdTags2Part,改进后使用下述的fat结构描述,并且将每个块内的fat结构统一存放在块的前面2个数据页中,而不再存放在OOB区内。这样在文件系统加载时,只要读取每个块的前2个页的数据,减少了加载时间。
该数据结构中的inodeId用于唯一标识分区内某个文件的ID,serialNum在断电保护实现中用于标识数据存储的先后顺序,chunKIn Inode表示文件数据的第n个扇区号,chunKInFlash表示存储位置即页号。从中可以看出,每个fat对象的大小是4 Byte,加载文件系统时,通过读取各个存储块起始处的fat对象,就可以知道每个扇区的数据所对应的文件信息,为每个文件建立一个文件树成员,用于记录该文件数据的所有扇区。与YAFFS2原有的存储方式相比较,重复存放在每个扇区的OOB区域的序列号和字节数信息就不再需要了,因为序列号是描述整个存储块的,每个存储块只需要记录一次。而原有的字节数是用于记录某个文件的最后一个扇区数据的字节数,不适合存储在每个扇区的OOB区域中,所以这个可以被优化处理,改进后在yaffs_Object结构中增加描述信息,记录存放某个文件的最有一个扇区的有效数据的字节数。如图2描述了改进后的Flash存储器的每个块存储的数据信息,第1个页存放的是序列号和该存储块的所有fat信息,其余各页是数据区,存储文件内容或文件属性,而fat结构包含了所有页到文件的索引信息。
图2 Flash存储块
当需要分配空闲块存储数据时,将文件系统当前的序列号加1,记录到新分配的空闲块的开始4 Byte,设置该块为分配状态,第一个页被用作存储fat索引信息,从第2个页开始可以用于存储文件数据,分配和写入必须严格按照顺序,当文件系统将某文件的数据写入到某个页时,同时要构造好相应的fat索引结构,写入第1个页的相应位置。在实现中yaffs_AllocChunK()用于分配存储页,在该分配算法中,首先从当前分配状态块中分配页,若全部已分配,就从分区的空闲列表中找到一个空闲块,继续上述过程。在使用过一段时间后,系统中所有的空闲状态的块都是由垃圾回收而来的,所以合适的磨损平衡和垃圾回收策略[9]可以以类似的概率处理分区中的各个存储块,从而均衡地使用各个存储块,这样各存储块的扇区的擦写次数均匀,能有效地延长存储器的寿命。
3.2 文件系统的加载过程
改进后,加载某个文件系统分区时,其主要操作分2个步骤:首先,依次读每个存储块开始处的序列号,其有效值范围为0x1000-0xefffff00,还有一些特殊的值用于标记特殊状态的块。序列号在断电保护和垃圾回收过程中都会被用到;然后,将分区内的所有存储块以其相应的序列号进行排序,依次读取其数据并进行分析处理,其主要流程如图3所示。
图3 初始化加载流程
每个存储块的第1个页存储了该块所有页的fat结构,每个fat实例是相应存储页的索引信息,包含了其所属文件信息,文件序列号等,当某个fat对象中的文件页号为0时,标识该fat索引的存储页存储的是该文件的文件头,获得相应的存储页号,调用驱动读取文件头信息,使用该文件头构造完整的文件属性信息。当文件页号为其他值时,则表明其索引的存储页存放的是文件数据,记录该页号到文件的索引树中,用于后面对文件数据的读写操作。当所有的存储块处理完之后,文件系统的加载过程就基本完成了,分区上所有文件和目录的信息都被完整的建立了,后面通过文件系统提供的接口对文件的读、写与管理等操作是基于这些信息实现的。
3.3 断电保护机制
便携式电子设备使用过程中,如果突然断电,且此时有应用在进行文件的更新,就可能导致操作中止,文件系统信息由于没有同步地进行更新而不完整,进而导致重启系统加载分区时失败。
所以,YAFFS2文件系统在实现各种文件操作时,就要考虑到各种文件操作的原子性,其实现方法主要就是存储一些冗余信息保证文件系统的完整性。例如,在实现文件删除操作时,为每个分区定义一个delete目录,当删除某个文件时,仅修改目录树结构,使该文件挂在该目录下;当需要更新文件的目录信息和文件数据时,只是将新的数据写入一个新的页,然后将原有数据页的OOB的标志位设置为无效。在更新文件数据时,会同时更新页的数据区和OOB区,若在这个过程中任何时候断电,就会导致最后写入的OOB区域数据不完整,该写入操作就不会破坏分区数据的完整性,下次加载时,原有数据会被作为有效数据处理,不完整的新数据会被当作无效数据页被丢弃掉。
改进后,当要改变文件的目录树结构时,会为该文件写入新的文件头,其中包含了该文件新的父目录的ID等目录结构信息,在写入时,并不是更新原有的数据页,而是写入一个新的数据页,由于写任何数据页都需要构造fat索引结构,并将该索引结构写入同一个存储块的第1页,这样就存在2个写操作,且一个是写入第1页,一个是写入另外一个页,当在这2个页的写操作中间意外断电时,重启后加载文件系统时,会发现2个存储页包含相同相同的文件头信息。所以必须进行特别的处理来保证断电保护性能,在实现中,为了能从这2个冲突的存储页中区分开来,就需要用到上述的每个fat结构中的序列号和每个存储块起始处的序列号,其设计原理如图4所示。当需要将某存储块中比较新的数据写入新的存储页时,就将相应的fat结构中的序列号递增,并随之写进存储块中,若这时意外断电,就可以根据两个存储页对应的fat结构中的序列号来判断哪个是原有数据,哪个是新的数据,从而保证文件系统的完整性;如果只是更新数据页,fat结构中的序列号不用递增,因为即使意外断电,重启加载时,根据存储块的序列号就可以知道哪个是最后写入的有效存储页,哪个是旧的需要更新的数据页,这是因为每个存储块的序列号代表了其上面存储的文件的先后顺序,它是文件系统在分配块时计算并写入的。
图4 断电保护原理
3.4 垃圾回收策略
使用过程中,修改文件内容、删除文件会使得Flash存储块的部分扇区不再包含有效的数据,Flash存储器的特性决定了这些区域在整个块被擦除之前不可重写,将这些扇区所在的块内的有效数据重新存储然后擦除该块,并将其再次作为空闲块,这个过程便称为垃圾回收。
在现有YAFFS2文件系统的垃圾回收处理过程中,当文件系统需要向Flash存储器中写入数据时,先检查分区内的空闲擦除块的个数,若低于设定的文件系统的保留值,便启动垃圾回收线程,调用垃圾回收处理函数找出无效数据页最多的存储块,然后将该存储块内的所有有效数据写入当前正在使用的块,最后调用驱动将该存储块擦除,供以后分配使用[10]。
在改进后的垃圾回收处理过程中,垃圾回收操作的实现是用一个线程Garbage Collection线程实现的,并将它放入一个信号量的等待队列中,或当需要向设备写数据时,或者每隔一段设置好的时间,去唤醒该线程。该线程首先统计分区内空闲存储块的数量,决定是否要启动回收处理,如果空闲块数少于预设的保留块数,则从分区的处于使用状态的列表中找出无效数据最多的存储块,并进行回收,否则从整个分区中找到最脏块进行回收。
回收的主要过程如图5所示,回收过程中找最脏块的2个策略包括无效数据扇区最多和序列号最小,即效率原则和均衡原则结合使用,达到存储块的均衡使用。从图5中可以看出,主要根据每个存储块开始4 Byte序列号知道存储块的使用顺序,序列号越大表明越早被使用,从而垃圾回收处理应该越早地回收该存储块,不会导致某个块对应的文件数据被频繁的更改而重复擦写,一定程度上保证了存储块的均衡使用。当回收某个脏块时,将该存储块中所有有效数据读出,复制到分区的分配存储块,对于每个扇区数据都要构造相应的fat索引结构,如文件页号、Flash页号等,并将其顺序地写入相应存储块的第一个页,这样就完成了数据的复制。最后将原来的脏块加入回收列表,触发驱动的擦除操作,将整个块擦除,并标记该块为空闲块,加入到分区的空闲列表,供后面分配使用。
图5 垃圾回收算法
下面基于一款数字电视平台对文件系统的安装时间,读写速度和损耗平衡性能进行测试和分析,该硬件平台同时支持NAND、NOR存储器并有MMC控制器支持MMC卡,由于它们的存储空间不同,在下面的测试中统一格式化一个8 MB的分区,并进行相应测试。
4.1 文件系统加载时间
YAFFS2文件系统分区加载时,读取每个存储块的状态信息,然后根据其状态分别读取文件系统信息,对于原有的YAFFS2,是通过读存储块的每个页的OOB区域,而改进后的YAFFS2只是读取每个存储块的第一个页,它包含了当前块所有页的索引fat结构。在测试过程中,选择一些随机文件做一个YAFFS2镜像文件,通过各自的格式化工具写到存储分区上,然后加载相应的分区,对于NOR Flash和MMC卡,分别采用各自的格式化工具格式化为JFFS2和FAT32文件系统[11]。
测试的加载时间如表2所示,从中可以看出,对于NAND分区,改进后的安装时间减少约25%;对于NOR分区,加载时间明显减少,这是因为JFFS2文件系统加载时需要以字节为单位扫描解析每个存储页,是JFFS2的主要缺点;而对于MMC分区,FAT32只需要读取fat表就完成加载,所以时间明显减少。
表2 分区加载时间 s
4.2 文件读写速度
安装文件系统后,分别进行文件读、写、删除操作的性能测试,其中读速度是通过将文件拷贝到系统的tmpfs分区得到的,写速度是通过将文件从tmpfs分区写入YAFFS2分区。读写tmpfs分区的时间可以忽略,所以测试数据基本等于文件的读写速度。
测试时使用tim e命令来记录读写100 KB文件的时间,改进前后的YAFFS2测试结果如表3和表4所示。
表3 改进前文件存取时间 s
表4 改进后文件存取时间 s
测试结果表明,对于NAND存储器,改进前后文件的读写速度差别很小,而NOR,MMC卡的读写速度与NAND的差别大。这是因为文件读写速度主要由存储器驱动的读写速度决定,这些存储器的读写速度差别大,对于文件删除操作,其速度相似是由于在实现删除操作时,只是在文件系统信息中做一些标志的更新,不需要同步写入存储器,所以其速度快,即使文件大小不同,其删除速度也较为接近。
4.3 损耗平衡性能
由于Flash存储器的每个块的擦除次数是有限的,因此应可能地均衡擦除分区的每个存储块,延长存储器的整体使用寿命。为了统计每个存储块的擦除次数,使用一个全局列表来记录每个块的擦除次数,并在驱动的擦除操作中更新该列表,当擦除某个块时,就将相应的计数递增。然后,通过文件拷贝和删除命令,对测试分区上的文件进行大量的改写操作,并做一些压力测试。最后统计得出各存储块的擦除次数分布,实际测试结果表明,分区上的各存储块被均衡地使用,垃圾回收操作的2个回收策略达到了预期的效果。
本文从Flash存储器管理、文件的创建和读写的实现分析YAFFS2文件系统的设计原理,提出一种新的存储方式,分别从文件系统安装过程、垃圾回收、掉电保护机制方面对YAFFS2进行改进,并设计文件系统镜像格式化工具。在系统平台上进行了安装时间、读写速度和损耗平衡性能的测试,结果表明改进的文件系统安装时间有所减少,并能使Flash各存储扇区被均衡使用。但由于各种Flash存储器每个块的存储页数差别较大,可能会导致fat结构未必能全部存储在首页,因此下一步将针对一些特殊的Flash存储器要求改进fat结构,使其具有更广泛的适用性。
[1] W okey.YAFFS NAND Flash Filesystem[EB/OL].(2007-03-05).http://www.aleph1.co.uk/yaffs/.
[2] A leph One Ltd..Yaffs2 Specification[EB/OL].(2007-06-08).http://www.yaffs.net/yaffs-2-specification.
[3] 毛德操,胡希明.Linux内核源代码情景分析[M].杭州:浙江大学出版社,2001.
[4] 郭玉东.Linux操作系统结构分析[M].西安:西安电子科技大学出版社,2004.
[5] Manning C.Flash File System Considerations[EB/OL].(2009-02-03).http://www.yaffs.net/sites/yaffs.net.
[6] 陈莉君.Linux操作系统内核分析[M].北京:人民邮电出版社,2003.
[7] Manning C.How YAFFSWorks[EB/OL].(2010-09-05). http://www.yaffs.net/sites/yaffs.net/files/How Yaffs W orks.pdf.
[8] Hoog A.Android YAFFS2 Support[EB/OL].(2014-10-08). http://www.basistech.com/wp-content/uploads/2014/04.
[9] Zimmermann C.Forensic Analysis of YAFFS2[EB/OL].(2012-04-09).http://aleph1.co.uk/gitweb?p=yaffs2.git.
[10] Pooters I.Yaffs Object Header[EB/OL].(2010-06-08). http://sandbox.dfrws.org/2011/fox-it/DFRWS2011_results/ Report.
[11] 宋 聿,蒋烈辉,董卫宇,等.一种独立式I/O虚拟化方法研究[J].计算机工程,2014,40(10):81-85.
编辑 金胡考
Research and ImProvement of YAFFS2 File System Based on Em bedded Linux
ZHU Shaoying,ZHA Qipeng
(The 32nd Research Institute of China Electronics Technology Group Corporation,Shanghai 200233,China)
YAFFS2 file system is NAND Flash only file system.This paper analyzes the design principle of YAFFS2 based on embedded Linux in two aspects of Flash storage and filemanagement.Aiming at two limitations of long mount time and applicable only on NAND Flash,it proposes a new layout of file system key data and structure,and improves YAFFS2 in aspects of storage management,file system initialization,garbage collection and power off protection to reduce mount time and to make it applicable on other Flash.Test result show s that it can reducemount time by 25%and balance erasure of every block as expected.
YAFFS2 file system;NAND Flash;embedded Linux system;garbage collection strategy;wear-leveling
朱绍英,查启鹏.基于嵌入式Linux的YAFFS2文件系统研究与改进[J].计算机工程,2015,41(9):292-297,302.
英文引用格式:Zhu Shaoying,Zha Qipeng.Research and Improvement of YAFFS2 File System Based on Embedded Linux[J].Computer Engineering,2015,41(9):292-297,302.
1000-3428(2015)09-0292-06
A
TP391
10.3969/j.issn.1000-3428.2015.09.054
朱绍英(1983-),女,工程师,主研方向:嵌入式Linux系统;查启鹏,工程师。
2015-04-07
2015-05-19 E-m ail:zhushaoying181@163.com