您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 公司方案 > Nand flash文件系统总结
NANDflash文件系统目前flash的文件系统比较多,用的比较多的就是JFFS2文件系统。基于NORflash上的JFFS2文件系统可以说算是比较成熟了,支持NANDflash的JFFS2也已经发布了。源代码可以到上面下载。但是在我的测试过程中,在nandflash上挂接的JFFS2文件系统很不稳定,经常有CRC错误产生。特别是进行写操作的时候,每次复位都会产生CRC错误,可以说支持NANDflash的JFFS2文件系统目前还不成熟。而YAFFS文件系统则是专门针对NANDflash的,源代码可以到上下载。在测试过程中稳定性能比JFFS2文件系统要稳定的多,而且mount分区的时间也比JFFS2文件系统少的多。用JFFS2mount一个2m的文件系统大约需要1s。下面分别介绍在uclinux下面使用JFFS2和YAFFS文件系统。1、JFFS2到压缩包。压缩包里面还有有关的内核补丁和一些MTD的相关工具。主要的补丁就是ilookup-2.4.23.patch,因为最新的MTD驱动中要用到一个ilookup()函数。打完补丁、更新了MTD驱动和JFFS2文件系统之后就开始写自己nandflash驱动了。如果不想把JFFS2作为根文件系统的话,还需要修改MTD_BLOCK_MAJOR。驱动可以参考里面的例子,最简单的就是参考spia.c。写驱动主要工作是定义flash分区结构、定义flash读写地址、写控制flash的**_hwcontrol()函数。具体的操作要看所用的nandflash的芯片资料。相对NORflash来说驱动要简单多了。:)改完之后再配置MemoryTechnologyDevices(MTD)下CONFIG_MTD=YCONFIG_MTD_DEBUG=YCONFIG_MTD_DEBUG_VERBOSE=3CONFIG_MTD_PARTITIONS=YCONFIG_MTD_CHAR=YCONFIG_MTD_BLOCK=YNANDFlashDeviceDrivers下CONFIG_MTD_NAND=Y定义自己的驱动文件Filesystems下CONFIG_JFFS2_FS=YCONFIG_JFFS2_FS_DEBUG=2CONFIG_JFFS2_FS_NAND=y/*这个是新加的*/在uClinuxv1.3.4Configuration下FlashTools下CONFIG_USER_MTDUTILS=YCONFIG_USER_MTDUTILS_ERASE=YCONFIG_USER_MTDUTILS_ERASEALL=YCONFIG_USER_MTDUTILS_MKFSJFFS2=Y最后就是辛苦了调试工作了。:(MTD驱动调试完之后,就可以在上面挂接JFFS2文件系统了。参看flash分区情况:cat/proc/mtd,擦除分区:eraseall/dev/mtd*.例如把第一个分区mount到/mnt目录下面:先:eraseall/dev/mtd0然后:mount-tjffs2/dev/mtdblock0/mnt2、YAFFSYAFFS意义为'yetanotherflashfilesystem',也是一个开源的文件系统。YAFFS是目前为止唯一一个专门为NANDflash设计的文件系统,具有很好的可移植性,能够在linux,uclinux,和wince下面运行。在上下载源代码。压缩包里面也包含YAFFS的说明文档。YAFFS文件系统的源文件就devextras.h,yaffs_ecc.c,yaffs_ecc.h,yaffs_guts.c,yaffs_guts.h,yaffs_mtdif.h,yaffs_mtdif.c和yportenv.h另外需要配置的宏:CONFIG_YAFFS_FS和CONFIG_YAFFS_MTD_ENABLED,就是配置在mtd上面挂接YAFFS,其它还有一些辅助配置需要时也可以配置。在fs目录下面建一个yaffs目录,把以上说的文件考里面去,新建一个makefile:O_TARGET:=yaffs.oobj-y:=yaffs_fs.oyaffs_guts.oyaffs_mtdif.oyaffs_ecc.oobj-m:=$(O_TARGET)include$(TOPDIR)/Rules.make接下来就是改fs目录下面config.in和makefile,在配置YAFFS的时候,把YAFFS连接进去。如果像前面一样已经把NANDMTD驱动调好了,加YAFFS就很简单了。因为YAFFS是自己做ECC校验的,所以要把MTD驱动里面的ECC去掉。在驱动里面改成this-eccmode=NAND_ECC_NONE就可以了。另外YAFFS是用mkyaffs来擦除flash,所以在mtd-utils中加上mkyaffs.c,一起编译进去。最后就是编译了,呵呵。中间会有一些警告没有关系的,就是写没有用的变量和函数,不过话说回来YAFFS的代码写的确实不太规范。当然它的性能确实没话说。有兴趣的可以试一下-。1.JFFS2文件系统JFFS2是JFFS的后继者,由RedHat重新改写而成。JFFS2的全名为JournallingFlashFileSystemVersion2(闪存日志型文件系统第2版),其功能就是管理在MTD设备上实现的日志型文件系统。与其他的存储设备存储方案相比,JFFS2并不准备提供让传统文件系统也可以使用此类设备的转换层。它只会直接在MTD设备上实现日志结构的文件系统。JFFS2会在安装的时候,扫描MTD设备的日志内容,并在RAM中重新建立文件系统结构本身。除了提供具有断电可靠性的日志结构文件系统,JFFS2还会在它管理的MTD设备上实现“损耗平衡”和“数据压缩”等特性。节点头部定义和兼容性JFFS2将文件系统的数据和原数据以节点的形式存储在闪存上,具体来说节点头部的定义如下:图一幻数屏蔽位:0x1985用来标识JFFS2文件系统。节点类型:JFFS2自身定义了三种节点类型,但是考虑到文件系统可扩展性和兼容性,JFFS2从ext2借鉴了经验,节点类型的最高两位被用来定义节点的兼容属性,具体来说有下面几种兼容属性:JFFS2_FEATURE_INCOMPAT:当JFFS2发现了一个不能识别的节点类型,并且它的兼容属性是JFFS2_FEATURE_INCOMPAT,那么JFFS2必须拒绝挂载(mount)文件系统。JFFS2_FEATURE_ROCOMPAT:当JFFS2发现了一个不能识别的节点类型,并且它的兼容属性是JFFS2_FEATURE_ROCOMPAT,那么JFFS2必须以只读的方式挂载文件系统。JFFS2_FEATURE_RWCOMPAT_DELETE:当JFFS2发现了一个不能识别的节点类型,并且它的兼容属性是JFFS2_FEATURE_RWCOMPAT_DELETE,那么在垃圾回收的时候,这个节点可以被删除。JFFS2_FEATURE_RWCOMPAT_COPY:当JFFS2发现了一个不能识别的节点类型,并且它的兼容属性是JFFS2_FEATURE_RWCOMPAT_COPY,那么在垃圾回收的时候,这个节点要被拷贝到新的位置。节点总长度:包括节点头和数据的长度。节点头部CRC校验:包含节点头部的校验码,为文件系统的可靠性提供了支持。节点类型JFFS2定义了三种节点类型:JFFS2_NODETYPE_INODE:INODE节点包含了i-节点的原数据(i节点号,文件的组ID,属主id,访问时间,偏移,长度等),文件数据被附在INODE节点之后。除此之外,每个INODE节点还有一个版本号,它被用来维护属于一个i-节点的所有INODE节点的全序关系。下面举例来说明这个全序关系在JFFS2的使用:图二因此,当文件系统从闪存上读节点信息后,会生成下面的映射信息:图三根据这个映射信息表,文件系统就知道到相应的INODE节点去读取相应的文件内容。最后要说明的是,JFFS2支持文件数据的压缩存储,因此在INODE节点中还包含了所使用的压缩算法,在读取数据的时候选择相应的压缩算法来解压缩。JFFS2_NODETYPE_DIRENT:DIRENT节点就是把文件名与i节点对应起来。在DIRENT节点中也有一个版本号,这个版本号的作用主要是用来删除一个dentry。具体来说,当我们要从一个目录中删除一个dentry时,我们要写一个DIRENT节点,节点中的文件名与被删除的dentry中的文件名相同,i节点号置为0,同时设置一个更高的版本号。JFFS2_NODETYPE_CLEANMARKER:当一个擦写块被擦写完毕后,CLEANMARKER节点会被写在NORflash的开头,或NANDflash的OOB(Out-Of-Band)区域来表明这是一个干净,可写的擦写块。在JFFSv1中,如果扫描到开头的1K都是0xFF就认为这个擦写块是干净的。但是在实际的测试中发现,如果在擦写的过程中突然掉电,擦写块上也可能会有大块连续0xFF,但是这并不表明这个擦写块是干净的。于是我们需要CLEANMARKER节点来确切的标识一个干净的擦写块。JFFS2节点,擦写块在内存中的表示和操作JFFS2维护了几个链表来管理擦写块,根据擦写块上的内容,一个擦写块会在不同的链表上。具体来说,当一个擦写块上都是合法(valid)的节点时,它会在clean_list上;当一个擦写块包含至少一个过时(obsolete)的节点时,它会在dirty_list上;当一个擦写块被擦写完毕,并被写入CLEANMARKER节点后,它会在free_list上。通常情况下,JFFS2顺序的在擦写块上写入不同的节点,直到一个擦写块被写满。此时JFFS2从free_list上取下一个擦写块,继续从擦写块的开头开始写入节点。当free_list上擦写块的数量逐渐减少到一个预先设定的阀值的时候,垃圾回收就被触发了,为文件系统清理出更多的可用擦写块。为了减少对内存的占用,JFFS2并没有把i节点所有的信息都保留在内存中,而只是把那些在请求到来时不能很快获得的信息保留在内存中。具体来说,对于在闪存上的每个i节点,在内存里都有一个structjffs2_inode_cache与之对应,这个结构里保存了i节点号,指向i节点的连接数,以及一个指向属于这个i节点的物理节点链表的指针。所有的structjffs2_inode_cache存储在一个哈希表中。闪存上的每个节点在内存中由一个structjffs2_raw_node_ref表示,这个结构里保存了此节点的物理偏移,总长度,以及两个指向structjffs2_raw_node_ref的指针。一个指针指向此节点在物理擦写块上的下一个节点,另一个指针指向属于同一个i-节点的物理节点链表的下一个节点。图四在闪存上的节点的起始偏移都是4字节对齐的,所以structjffs2_inode_cache中flash_offset的最低两位没有被用到。JFFS2正好利用最低位作为此节点是否过时的标记。下面举一例来说明JFFS2是如何使用这些数据结构的。VFS调用iget()来得到一个i节点的信息,当这个i节点不在缓存中的时候,VFS就会调用JFFS2的read_inode()回调函数来得到i节点信息。传给read_inode()的参数是i节点号,JFFS2用这个i节点号从哈希表中查找相应的structjffs2_inode_cache,然后利用属于这个i节点的节点链表从闪存上读入节点信息,建立类似于表三的映射信息。JFFS2挂载过程JFFS2的挂载过程分为四个阶段:1)JFFS2扫描闪存介质,
本文标题:Nand flash文件系统总结
链接地址:https://www.777doc.com/doc-4042327 .html