YAFFS文件系统简介

来源:互联网 发布:如何学好犀牛软件 编辑:程序博客网 时间:2024/04/28 17:46

本文转自:http://www.360doc.com/content/11/0630/21/7204565_130670822.shtml

一、YAFFS文件系统简介

     YAFFS(Yet Another Flash File System)文件系统是专门为NandFlash设计的文件系统,有些类似与JFFS/JFFS2文件系统,不同之处是JFFS/JFFS2文件系统最初是为NorFlash的应用场合设计的,而NorFlash和NandFlash本质上有较大的区别(坏块、备用区、容量),所以尽管JFFS/JFFS2文件系统也能应用于NandFlash,但由于它的内存占用和启动时间针对NorFlash做了特殊取舍,所以对于NanFlash来说通常不是最优方案(性能较低和启动速度稍慢)。而YAFFS利用NandFlash提供的每个页面16字节或64字节的Spare区(备用区)空间来存放ECC和文件系统的组织信息,能够实现错误检测和坏块处理。这样的设计充分考虑了NandFlash以页面为存取单元的特点,将文件组织成固定大小的数据段,能够提高文件系统的加载速度。(垃圾回收算法+贪心算法)

 

     YAFFS目前有YAFFS、YAFFS2两个版本(YAFFS3还在研发阶段,没有面市),一般来说,YAFFS对小页面(512B+16B/页)有很好的支持,YAFFS2对更大的页面(2K+64B/页)支持更好。

 

 

二、YAFFS文件系统在NandFlash上的组织方式

     YAFFS对文件系统上的所有内容(比如正常文件,目录,链接,设备文件等等)都统一当作文件来处理,每个文件都有一个页面专门存放文件头,文件头保存了文件的模式、所有者ID、组ID、长度、文件名、Parent Object ID等信息。因为需要在一页内放下这些内容,所以对文件名的长度,符号链接对象的路径名等长度都有限制。

 

     YAFFS充分利用了NandFlash的“备用区”空间,这个备用空间是指每个页的16自己的Spare区,通常不作为存储数据的空间。YAFFS用了其中的6个字节作为页面数据的ECC,1个字节用作坏块状态标志字,1个字节用作数据状态标志字,其余的8个字节用来存放文件系统的组织信息。详细阅读Linux源码中yaffs\yaffs_guts.h文件中yaffs_Spare数据结构,参见下图所示:

 

     以512B+16B为一页(16B表示每页面的备用空间为16字节)的NandFlash K9F1208为例,文件系统数据的存储结构如下表所示。

字节起始

字节终止

长度(字节)

内容描述

0

511

512

数据区域(文件数据或文件头)

512

515

4

YAFFS TAG1

516

516

1

数据状态标志字

517

517

1

坏块状态标志字

518

519

2

YAFFS TAG2

520

522

3

后256字节数据的ECC校验结果

523

524

2

YAFFS TAG2

525

527

3

前256字节数据的ECC校验结果

表格  YAFFS文件系统数据的存储布局

 

     这里YAFFS文件系统共使用了8个字节(64Bit)用来存放文件系统相关的信息,这8个字节的具体使用情况,请详细阅读Linux源码中yaffs\yaffs_guts.h文件中yaffs_Tags数据结构,请参见下图和下表所示。

位数

内容

说明

20

ChunkId

该page在一个文件内的索引号,所以文件大小被限制512M

2

serialNumber

2位序列号

10

byteCount

该页内的有效字节数

18

objected

文件ID号,用来唯一标识一个文件

12

ECC

yaffs_Tags本身的ECC校验和

2

unusedStuff

UnUsed

表格 YAFFS文件系统组织信息分配表

 

     其中serialNumber在文件系统创建时初始化为0,以后每次写具有统一ObjectID和ChunkID的页的时候都加1,因为YAFFS文件系统在更新一个页的时候总是在一个新的物理页上写入数据,再将原先的物理也删除,所以根据SerialNumber,当新的页已经写入但老的页还没有被删除的时候用来时被正确的页,以保证特殊环境下(例如突然掉电),数据的正确性。

 

     由于文件系统的基本组织信息保存在页面的备用区中,因此,在文件系统加载时只需要扫描所有页面的备用区空间,即可建立在RAM中建立起整个文件系统的结构,从而大大加快了文件系统的加载速度。(比JFFS文件系统启动速度快的原因:JFFS需要扫描整个芯片数据并进行分析)

 

 三、YAFFS文件系统在内存上的组织方式

      通常一个具体的文件系统都会在VFS的SuperBlock结构中存储通用的数据结构,同时也有自己的私有数据。YAFFS文件系统的专有数据是yaffs_DeviceStruct的数据结构,主要用来存储软硬件配置信息,相关函数指针和统计信息等。

      YAFFS文件系统的SuperBlock块是在文件系统mount加载的过程中由read_super()函数填充的,由于物理上没有存储SuperBlock块,所以NandFlash上的YAFFS文件系统本身没有存储文件系统的魔术数,也是在文件系统加载的过程中直接赋值的。

      在执行read_super()函数的过程中,YAFFS文件系统需要将文件系统的目录结构在内存中建立起来。首先需要扫描YAFFS分区,根据从OOB中读取出来的yaffs_tags数据结构判断出是文件头页面还是数据页面。再根据文件头页面中的内容以及数据页面中的ObjectID、ChunkID、SerialNumber等信息在内存中为每个文件建立一个对应的yaffs_object对象,请详细阅读Linux源码中yaffs\yaffs_guts.h文件中yaffs_ObjectStruct数据结构。在yaffs_object对象中,主要包含了:

 

n         用作组织结构的,如指向父目录的Parent指针,指向同级目录中其他对象链表的siblings双向链表头结构;

 

n         用作YAFFS文件系统维护用的各种标记位如脏(dirty)标记,删除标记等等;

n         修改时间,用户ID,组ID等文件属性;

此外根据Object类型的不同(目录,文件,链接),对应于某一具体类型的Object,在yaffs_object中还有其各自专有的数据内容:

n         普通文件:文件尺寸,用于快速查找文件数据块的yaffs_Tnode 树的指针等;

n         目录:目录项内容双向链表头(children);

n         链接:softlink的alias,hardlink对应的ObjectID;

     除了对应于存储在NandFlash上的Object而建立起来的yaffs_object以外,在read_super()函数执行过程中还会建立一些虚拟对象(FAKE Object),这些Fake Object在NandFlash上没有对应的物理实体,比如在建立文件目录结构的最初,YAFFS会建立四个虚拟目录(FAKE Directory):rootDir, unlinkedDir, deleteDir, lostNfoundDir分别用作根目录,对象挂接的目录,delete对象挂接的目录,无效或零时数据块挂接的目录。

     通过创建这些yaffs_object,YAFFS文件系统就能够将存储在NandFlash上数据系统的组织起来,在内存中维护一个完整的文件系统结构。

 

 四、YAFFS文件系统对MTD的依赖

     YAFFS文件系统通常是运行在MTD之上的,因此需要根据实际应用修改MTD的驱动,以K9F4G08UOM为例子,找到driver/mtd/nand/smdk2440.c,修改:mtd_partition分区结构体、相关控制引脚函数smdkXXX_hwcontro、初始化函数smdkXXX_nand_init等函数,并将NandFlash驱动加入MTD子系统。

 

五、YAFFS文件系统的制作和移植

 

      yaffs源代码包的utils目录下包含了mkyaffsimage/mkyaffs2image的代码,简单的修改一下Makefile里的内核路径就能编译出mkyaffsimage/mkyaffs2image工具。运行mkyaffsimage dir imagename可以制作出yaffs文件系统的镜像。但是,需要注意的是,制作出来的yaffs image文件与通常的文件系统的image文件不同,因为在image文件里除了以512字节为单位的一个page的data数据外,同时紧跟在后还包括了16字节为单位的NandFlash备用区OOB的数据。所以实际上是以528个字节为单位的。就是因为包含了这额外的16字节/page的数据,所以通常的下载其它类型image的工具就无法正常下载yaffs image了,需要修改你所使用的下载工具的代码,使得它能将yaffs image中的这些额外数据也写入NandFlash OOB中。

      这里还有一点需要注意的是,通过mkyaffsimage制做出来的image其OOB中也包含它自己计算的ECC校验数据,其校验算法有可能和MTD驱动的校验算法不同,如果在内核中由MTD来处理ECC,会造成MTD认为所有的page都校验错误。要解决这个问题通常有两种方法:

第一、重新配置内核,进入文件系统模块的选择界面,选中"Lets Yaffs do its own ECC",同时将MTD中的ECC校验关闭。但是这种不校验数据ECC的做法,在系统使用过程中产生坏块位时,就会显示出系统的健壮和容错性很差。

第二、通过修改bootloader(比如uboot),在下载文件系统时,通过硬件计算并读出数据ECC,并修改image中的ECC后,将OOB数据写入到芯片中。

第三、推荐使用广州周立功发展有限公司的SmartPRO系列编程器,可以兼容并处理MTD驱动中的ECC与文件系统生成的ECC不一致的情况,又不需要修改mkyaffsimage代码,并且可以方便实现NandFlash烧录各种嵌入式操作系统的批量生



原创粉丝点击