文件系统是包括在一个磁盘(包括光盘、软盘、闪盘及其它存储设备)或分区中的目录结构;一个可应用的磁盘设备可以包含一个或多个文件系统;如果您想进入一个文件系统,首先您要做的是挂载(mount)文件系统;为了挂载(mount)文件系统,您必须指定一个挂载点(所挂载的目录)。
mount –t filesystemtype filesystem mountpoint
e.g mount -t yaffs2 /dev/mtdblock1 /mnt
1. Yaffs用到的专用术语
Page : NAND里可访问的最小存储单元,是实际资源存储区,需要跟文件系统中"页"的概念区别开来.具有的属性:读,写;能被标记,表明其是否损坏;还有用于存放校验数据的oob 单元. Page大小有512字节的,也有2K字节的;针对此,oob区域也有不同大小,512B/Page的oob有16个字节,2KB/Page的oob就是前者的4倍,也就是说64个字节.
Block : NAND实现了快速的擦,就是因为有了它. 块结构有两种:小块和大块,小块NAND FLASH包含32个页,每页512+16字节;大块NAND FLASH包含64页,每页2048+64字节。
OOB :备用空间(SpareData,OOB),用来存储ECC校验/坏块标志等信息,每个Page都有自己的oob.
Chunk :Chunk是Yaffs文件系统里的概念,是文件访问的基本单元,表示的是yaffs_object所配置到的逻辑资源存储区。在yaffs中大小与page相同。
Object :构成Yaffs文件系统的各种元素,比如文件,目录,链接,设备等等.
2. yaffs文件系统介绍
2.1 简介
2.1.1应用场合
Yaffs(Yet Another FlashFile System)文件系统是专门针对NAND闪存设计的嵌入式文件系统,目前有YAFFS和YAFFS2两个版本,两个版本的主要区别之一在于YAFFS2能够更好的支持大容量的NAND FLASH芯片。
2.1.2 NOR和NAND的比较
基本上NOR比较适合存储程序代码,其容量一般较小(比如小于32MB),价格较高;而NAND容量可达1GB以上,价格也相对便宜,适合存储数据。一般来说,128MB以下容量NAND FLASH 芯片的一页大小为528字节,用来存放数据,另外每一页还有16字节的备用空间(SpareData,OOB),用来存储ECC校验/坏块标志等信息,再由若干页组成一个块,通常一块为32页16K.
与NOR相比,NAND不是完全可靠的,每块芯片出厂时都有一定比例的坏块存在,对数据的存取不是使用地址映射而是通过寄存器的操作,串行存取数据。
2.2 Yaffs文件系统数据在NAND上的存储方式
Yaffs对文件系统上的所有内容(比如正常文件,目录,链接,设备文件等等)都统一当作文件来处理,每个文件都有一个页面专门存放文件头,文件头保存了文件的模式,所有者id,组id,长度,文件名,Parent Object ID等信息。因为需要在一页内放下这些内容,所以对文件名的长度,符号链接对象的路径名等长度都有限制。
2.2.1 yaffs1文件系统
前面说到对于NAND FLASH上的每一页数据,都有额外的空间用来存储附加信息,通常NAND驱动只使用了这些空间的一部分,yaffs正是利用了这部分空间中剩余的部分来存储文件系统相关的内容。以512+16B为一个PAGE的NAND FLASH芯片为例,yaffs文件系统数据的存储布局如下所示: 0..511 |
数据区域 |
512..515 |
YAFFS TAG |
516 |
Data status byte |
517 |
Block status byte坏块标志位 |
518..519 |
YAFFS TAG |
520..522 |
后256字节数据的ECC校验结果 |
523..524 |
YAFFS TAG |
525..527 |
前256字节数据的ECC校验结果 |
可以看到在这里YAFFS一共使用了8个BYTE用来存放文件系统相关的信息(yaffs_Tags)。这8个Byte的具体使用情况按顺序如下:
Bits |
Content |
20 |
ChunkID,该page在一个文件内的索引号,所以文件大小被限制在2^20PAGE即512Mb |
2 |
2 bits serial number |
10 |
ByteCount该page内的有效字节数 |
18 |
ObjectID对象ID号,用来唯一标示一个文件 |
12 |
Ecc,Yaffs_Tags本身的ECC校验和 |
2 |
unused |
其中Serial Number在文件系统创建时都为0,以后每次写具有同一ObjectID和ChunkID的page的时候都加一,因为yaffs在更新一个PAGE的时候总是在一个新的物理Page上写入数据,再将原先的物理page删除,所以该Serial Number可以在断电等特殊情况下,当新的page已经写入但老的page还没有被删除的时候用来识别正确的page,保证数据的正确性。
ObjectID号为18bit,所以文件的总数限制在256k即26万个左右。
对于yaffs2因为针对chunk size大于1k的NAND FLASH,在tags各分量及总体尺寸上都做了修改,以便更快更好的处理大容量的NAND FLASH 芯片。由于Tag尺寸的增大,在512+16B类型的NAND FLASH 上就一个chunk对应一个page的情况,目前就无法使用yaffs2文件系统了(硬件存储方面)。
Yaffs2兼容yaffs1(注册yaffs2文件系统可以操作yaffs1的文件系统)。YAFFS文件系统会根据NANDFlash的页面的大小来主动的配置是使用YAFFS1还是YAFFS2。
2.2.2 yaffs2文件系统
设计yaffs2文件系统的初衷是对2kB大小每页,并且严格按照页顺序写的方式的NAND FLASH的支持。
yaffs2文件系统相对yaffs1具有下列优势:
· zero page rewrites means fasteroperation. (YAFFS1 uses a single rewrite in the spare area to delete a page).
· ability to exploit simultaneous pageprogramming on some chips.
· improves performance relative toYAFFS1 speed(write:1.5x to 5x, delete: 4x, garbage collection: 2x)
· lower RAM footprint (approx. 25% to50% of YAFFS1).
· Can support Toshiba/Sandisk MLCparts.
YAFFS2文件系统在设计时就充分考虑了大页NAND FLASH的结构,根据大页NAND FLASH以页面为单位存取的特点,将文件组织成固定大小的页,利用大页NAND FLASH 提供的每个面(2112B,其中前2048B存储数据)64B的备用空间(SpareData,OOB)来存放ECC和文件系统的组织信息,这样不仅能够实现错误检测和坏块处理,还能够提高文件系统的加载速度。
YAFFS2文件系统数据在NAND FLASH 的备用空间内的存储布局:
Field |
Comment |
Size for 2kb chunks |
blockState |
Block state. Non-0xFF for bad block |
1byte |
chunkID |
32-bit chunk Id |
4 byte |
objectID |
32-bit object Id |
4 byte |
nBytes |
Number of data bytes in this chunk |
2 byte |
BlockSequence |
Sequence number for this block |
4 byte |
tagsEcc |
ECC on tags area |
3 byte |
Ecc |
ECC,3 bytes/256 bytes of data |
24 byte |
Total |
|
42 byte |
blockSequence:记录着各块被分配出去的先后顺序,每分配出去一块,就加1。
垃圾回收策略:
YAFFS1删除数据页是通过将NAND FLASH的相应页的一个标志位字节(ObjectID)写为0实现的,而YAFFS2为了能支持某些特殊的NAND FLASH,垃圾回收器读NAND FLASH每页的OOB区,得到这个数据页所属的文件ID,若此文件在YAFFS2虚拟创建的unlinked目录下,则此数据页无效。
/kernel/fs/fs-writeback.c/__mark_inode_dirty 删除文件的函数
/kernel/fs/yaffs2/yaffs_guts.c/yaffs_create_initial_diràyaffs_create_fake_dir创建四个虚拟目录:unlinked, deleted,root and lost and found。
如何选择块则由一定的策略而定,如最少脏页块。如果回收块中有有效数据,则将有效数据复制到新的空闲扇区中,并重新对其进行映射。垃圾回收器的启动时机是在FLASH中可用的扇区低于一定的阈值或者FLASH中的脏扇区的时候。也就是说,当系统企图获得空闲扇区的时候,发现FALSH中的空闲扇区低于预期了,则开始垃圾回收来获取更多的空闲扇区。
具体代码:
Kernel/fs/yaffs2/yaffs_guts.c
Yaffs_vfs.c/ yaffs2_mountàyaffs2_internal_read_super_mtdà yaffs_inter