yaffs2源代码分析(经典,值得一阅)
yaffs2文件系统实现原理分析_带书签
1 概述YAFFS (Yet Another Flash File System )文件系统是专门针对NAND flash 设计的嵌入式文件系统,目前有YAFFS 和Y AFFS2两个版本,两个版本的主要区别之一在于Y AFFS2 能够更好的支持大容量的NAND flash 芯片。
YAFFS 文件系统有些类似于JFFS/JFFS2文件系统,与之不同的是JFFS/JFFS2文件系统最初是针对NOR flash 的应用场合设计的,而NORflash 和NAND flash 本质上有较大的区别,尽管JFFS/JFFS2文件系统也能应用于NANDflash ,但由于它在内存占用和启动时间方面针对NOR 的特性做了一些取舍,所以YAFFS2对NAND flash 来说通常才是最优的选择方案。
2 相关概念分析YAFFS2之前,把NAND flash 相关概念介绍下:NAND flash 由块(block)组成,块又由页(page)构成,擦除时以块为单位,读写时以页为单位,页又包含数据区和空闲区(OOB,Out-Of-Band),而Page 在YAFFS2中被称为Chunk ,其中的数据区用来存放实际的数据,OOB 用来存放附加信息实现NAND flash 的管理。
以T8000 AXMPFUA 单板使用的NANDflash 为例,每块Block: 128 pages ,每页Page: (8K + 448) bytes ,数据区为8K ,OOB 为448bytes ,如图1所示:Plane :4096blocks128 pages(8K+448)bytes图1 NAND flash 物理结构3 数据结构struct yaffs_dev 是YAFFS2文件系统最核心的数据结构,表示Y AFFS2文件系统的超级块,它建立了整个文件系统的层次结构,并衔接VFS 层和MTD 层,与struct super_block 、struct mtd_info 的关系如图2所示:图2 yaffs_dev与super_block、mtd_info层次关系下面围绕struct yaffs_dev这个最核心的数据结构开始,分段介绍它的含义,进而引出其他重要的数据结构:■param:存储文件系统重要的一些参数,以及与MTD层的接口函数□inband_tags:标志位,默认为0,即采用OOB(out of band)方式存储tags,可以通过挂载时指定inband-tags选项改变默认值□total_bytes_per_chunk:每个chunk总的字节数□chunks_per_block:每个block总的chunk数□spare_bytes_per_chunk:每个chunk包含OOB块的字节数□start_block:第一个可以使用的block□end_block:最后一个可以使用的block□n_reserved_blocks:为GC保留的block阈值□n_caches:缓冲区的个数,YAFFS2为减少数据的碎片以及提高性能为每个文件的写入提供了cache□no_tags_ecc:标志位,默认为0,即tags中包括ECC纠错信息,可以通过内核配置改变默认值,CONFIG_YAFFS_DISABLE_TAGS_ECC□is_yaffs2:标志位,默认为0,即Y AFFS,在挂载的过程中会根据识别的mtd->writesize自动转换成YAFFS2□refresh_period:刷新周期,刷新目的主要找出最旧的处于YAFFS_BLOCK_STATE_FULL状态的block,供GC作为gc_block使用□skip_checkpt_rd:标志位,默认为0,支持读取checkpoint,提高挂载速度的一个功能可以通过挂载时指定挂载选项no-checkpoint-read、no-checkpoint修改默认值□skip_checkpt_wr:标志位,默认为0,支持写入checkpoint,提高挂载速度的一个功能可以通过挂载时指定挂载选项no-checkpoint-write、no-checkpoint修改默认值□write_chunk_tags_fn:函数指针,在挂载的文件系统的时候会被初始,NANDflash写入接口函数:param->write_chunk_tags_fn = nandmtd2_write_chunk_tags;□read_chunk_tags_fn:函数指针,在挂载的文件系统的时候会被初始,NANDflash读取接口函数:param->write_chunk_tags_fn = nandmtd2_write_chunk_tags;□erase_fn:函数指针,在挂载的文件系统的时候会被初始,NAND flash擦除block接口函数:param->erase_fn = nandmtd_erase_block;□wide_tnodes_disabled:标志位,默认值为0,采用动态位宽,通过内核配置修改可采用静态位宽CONFIG_YAFFS_DISABLE_WIDE_TNODES■os_context:指向yaffs_linux_context结构指针,该结构存储Y AFFS2运行环境,如下:□context_list:通过该字段加入到yaffs_context_list全局链表中□dev:指向Y AFFS2文件系统超级块的指针□super:指向VFS层超级块的指针□bg_thread:Y AFFS2后台垃圾回收线程的指针□bg_running:启动和停止垃圾回收线程的标志位,1:启动,0:停止□gross_lock:互斥锁,保护整个超级块关键字段的互斥访问,粒度比较大□spare_buffer:OOB块的缓冲区□search_contexts:通过该字段把所有Directory Search Context组成链表□yaffs_mtd_put_super:卸载文件系统时被调用来清理super_block□readdir_process:解决使用NFS死锁问题加入的□mount_id:每个NAND flash分区挂载YAFFS2都分配不同的ID号■driver_context:指向mtd_info结构指针,mtd_info是MTD子系统核心的数据结构,主要是对底层硬件驱动进行封装,这里不再介绍■data_bytes_per_chunk:每个chunk总的字节数,和前面提到的total_bytes_per_chunk一样■chunk_grp_bits :采用静态位宽时超过tnode_width宽度之后的位数,采用动态位宽值恒为0■chunk_grp_size:由chunk_grp_bits转化而来的大小■tnode_width:采用静态位宽默认是16,采用动态位宽是由整个NAND flash中chunk数目计算得到■tnode_mask:位宽的mask,主要用于快速获取chunk id号■tnode_size:YAFFS_NTNODES_LEVEL0节点所占用的内存大小,单位:byte■chunk_shift:主要用来计算logical chunk index以及logical chunk offset■chunk_div:作用同chunk_shift,主要用于chunk大小不是2次幂的情况■chunk_mask:作用同chunk_shift,组合起来计算logical chunk offset■is_mounted:标志位,文件系统挂载时被置位Checkpoint是为提高挂载速度而引入的功能,作用同JFFS2的EBS,以空间来换取时间,卸载时通过在NAND flash上保存文件系统超级块快照,挂载时获取快照信息可以快速还原系统的状态。
YAFFS嵌入式文件系统原理分析
YAFFs是一种类似于JFFs/JFFs2的专门为NAND Flash 设计的嵌入式文件系统。与专为NOR Flash而设计的JFFs相 比,它减少了一些功能,因此速度更快、占用内存更少。
表1 NAND和NOR两种Flash技术比较
NAND
NOR
性能
读速度慢 写速度快 擦除速度4m8 大多数写入操作前先进行擦 除操作擦除单元更小题。当每次页被 重写时,serialNumber就增加一次,对比不同的seriaINumber就
可以找出当前的页。 chunkId非O值说明这是个数据chunk,并且标示这个
chunk在文件中的位置(除文件头外文件的第一个chunk其 chunkId就是1)。为。表示这个chunk包含的是文件头信息。
表2 chunk中字节分配
字节
用途
0..5ll 512..515 516 517
文件和文件头数据 标记 数据状态。如果超过4位是O,表示这一页是被 丢弃的 块状态
518..519 标记
520..522 523..524
chuIlk中第二个256字节数据的Ecc 标记
525..527 chunk中第一个256字节数据的Ecc
嵌入式蒸巯编程
EMBEDDED SYSTEM PROGRAMMING
深入理解yaffs2文件系统(一)
深⼊理解yaffs2⽂件系统(⼀)深⼊理解yaffs2⽂件系统(⼀)1、Flash⽂件系统1.1、背景已经有多种flash⽂件系统(FFSs)或flash块驱动(在之上运⾏⼀个常规的FS),同时都有优点或缺点。
Flash存储器有⾮常多的限制,这⾥就不⼀⼀列举了。
已经有各种⽅法解决这些限制,以提供⼀个⽂件系统。
必须认识到,“flash”,包括NOR和NAND,各⾃有不同的限制。
很容易被专业术语“flash”误导,误以为⽤于NorFlash的⽅法也⽴即适⽤于NandFlash。
Nand块驱动⼀般采⽤FAT16作为⽂件系统,但不够健壮,也不够贴近Flash的特性。
这些块驱动通过⼀个“本地--物理”的映射层来仿真可写的、类似于磁盘扇区的块。
当使⽤FAT16时,这些⽂件系统⼯作的相当好,它们内存消耗⼩,代码尺⼨也很⼩。
但就像所有基于FAT 的系统⼀样,它们很容易损坏(如,丢失簇)。
其他的途径则是设计整个⽂件系统,不是基于块驱动,⽽且是flash友好的,这允许更多的余地来解决上述所提到的问题。
当前有两个linux⽂件系统能⾮常好的⽀持NorFLash,那就是JFFS以及它的升级版本JFFS2。
这两者都提供⽇志机制,⼤⼤的提升了健壮性,这也是嵌⼊式系统特别重要的⼀个特性。
不幸的是,它们在RAM消耗和启动时间⽅⾯都不是很好。
JFFS在flash中的每⼀个journalling⽇志节点,需要⼀个基于RAM的jffs_node结构,每⼀个节点为48字节。
JFFS2做了⼀个⼤改进,通过剪裁相关的结构体(jffs2_raw_node_ref)⽽减少到16字节。
即使如此,在512字节页⼤⼩128M的NandFlash,按平均节点⼤⼩来算,也需要250000字节约4M⼤⼩。
JFFS和JFFS2在启动时,需要扫描整个flash阵列来查找journaling节点,并决定⽂件结构。
由于NAND容量⼤、慢、连续访问、需要ECC校验,这些特性将导致不可接受的、很长的启动时间。
基于Linux的大容量Yaffs文件系统性能优化与实现
基于Linux的大容量Yaffs文件系统性能优化与实现刘翠玲;时兴;孙晓荣;梁明全【摘要】针对Yaffs文件系统应用在大容量存储设备时所产生挂载速度慢的问题,提出一种新的改进方法,并在Yaffs2文件系统中进行了实现。
通过在Yaffs2文件系统中增加适当的偏移量,使得在扫描挂载文件系统时减少了不必要的扫描时间,从而加快了挂载的速度。
在最新的Yaffs2文件系统当中,依据该方法修改Yaffs2源代码,同时,在Linux系统上加入了对改进后文件系统的支持。
对改进前后的性能进行分析和实验,表明了该方法的可行性。
%AimingattheproblemofslowmountspeedofYaffsfilesystemoccurredwh entobeappliedinstoragedeviceswithlarge capacity,we propose a new improved method,and implement it in Yaffs2 file system.By adding appropriate offset in Yaffss file system,the unnecessary scanning time is reduced when scanning the mounting file system,thereby the mounting speed is accelerated.In latest Yaffs2 file system,we modify the source code of Yaffs2.Meanwhile,we add the support to the modified Yaffs file systemin the Linux system,and analyse the performance before and after the modification.Experiments demonstrate the feasibility of the method.【期刊名称】《计算机应用与软件》【年(卷),期】2014(000)009【总页数】3页(P37-39)【关键词】Yaffs;文件系统;Linux;Flash【作者】刘翠玲;时兴;孙晓荣;梁明全【作者单位】北京工商大学计算机与信息工程学院北京 100048;北京工商大学计算机与信息工程学院北京 100048;北京工商大学计算机与信息工程学院北京100048;北京工商大学计算机与信息工程学院北京 100048【正文语种】中文【中图分类】TP3150 引言在科技高速发展的今天,尤其是以安卓系统为基础的一系列电子产品不断的发展,智能手机,平板电脑,智能电视,数码相机等等的一系列产品都离不开文件系统的支持。
yaffs2分析(原)
yaffs2分析(原)文件系统的重要作用就是对文件或者文件夹的数据进行相应的管理,无论是文件数据还是文件夹里面的内容数据在文件系统看来就是一个个元数据(metadata)。
文件系统就是实现这些元数据的相应管理。
由于yaffs2 是一个相对比较简单的文件系统,下面通过yaffs的启动过程看看yaffs文件元数据的组织。
由于Yaffs是基于nand flash 的,由于nand所特有的一些特性,所以yaffs就有了一些自身文件系统所特有的一些特性。
如文件的结构信息是保存在spare 里面的,无论是文件夹数据还是文件数据,都是保存到spare数据的。
typedef struct {unsigned sequenceNumber;unsigned objectId;unsigned chunkId;unsigned byteCount;} yaffs_PackedTags2TagsPart;保存在spare 里面的yaffs2结构如上。
在yaffs启动时候,如果checkpoint没有响应的保存掉电时的结构的话,就需要进行一下全盘的扫描,其中的扫描主要是在yaffs_scan里面完成的,文件系统结构的创建就是主要在这个scan的过程中实现的。
static int yaffs_Scan(yaffs_Device *dev){1 首先就是要对全盘的block 块进行相应的扫描,主要就是扫描出坏的块/* Scan all the blocks to determine their state */bi = dev->blockInfo;for (blk = dev->internalStartBlock; blk <= dev->internalEndBlock; blk++) {}2 对于坏的块进行相应的标记玩之后,就是逐个对block 里面每一个page进行扫描,并建立相应的结构/* For each chunk in each block that needs scanning....*/for (c = 0; !alloc_failed && c < dev->param.nChunksPerBlock &&state == YAFFS_BLOCK_STATE_NEEDS_SCANNING; c++) {if (!tags.chunkUsed) {如果是一个未被使用的page的话由系统进行回收。
yaffs2源码分析
狗拿耗子YAFFS2———狗拿耗子第三篇 1、YAFFS2 的背景 YAFFS2 是 Charles Manning 开发的 NAND Flash 文件系统。
可以从 获得详细 的描述和最新的版本。
关于 Nand Flash 与 Nor Flash 的不同之处,网上有很多文章叙述,这 里不再罗嗦。
反正是在嵌入式系统中,一般是 Nor Flash 存放在 Boot 程序,Nand Flash 作为 正式的存储设备使用。
YAFFS (Yet Another Flash File System) was designed and written by Charles Manning, of Whitecliffs, New Zealand, for the company Aleph One. YAFFS is the first file system that was designed specifically for NAND flash. Yaffs1 is the first version of this file system and works on NAND chips that have 512 byte pages + 16 byte spare (OOB;Out-Of-Band) areas. These older chips also generally allow 2 or 3 write cycles per page, which YAFFS takes advantage of - i.e. dirty pages are marked by writing to a specific spare area byte. Newer NAND flash chips have larger pages, 2048 bytes + 64 bytes spare areas, and stricter write requirements. Each page within a block must be written to in sequential order, and each page must be written only once. YAFFS2 was designed to accommodate these newer chips. YAFFS2 is based on the YAFFS1 source code, with the major difference being that internal structures are not fixed to assume 512 byte sizing, and a block sequence number is placed on each written page. In this way older pages can be logically overwritten without violating the "write once" rule. YAFFS is a robust log-structured file system that holds data integrity as a high priority. A secondary YAFFS goal is high performance. YAFFS will typically outperform most alternatives. It is also designed to be portable and has been used on Linux, WinCE, pSOS, eCOS, ThreadX and various special-purpose OSes. A variant 'YAFFS/Direct' is used in situations where there is no OS, embedded OSes and bootloaders: it has the same core filesystem but simpler interfacing to the OS and NAND flash hardware. The filesystem is licensed both under the GPL and under per-product licences available from Aleph One. YAFFS1 YAFFS has no inherent formatting, an erased flash chip is formatted. It follows the smart media scheme of marking the 5th byte of the spare area for bad blocks, and ignores any blocks where the spare area byte 5 is not 0xFF. To write file data, YAFFS initially writes a whole page (chunk in YAFFS terminology) that describes the file metadata, such as timestamps, name, path, etc. The new file is assigned a unique object ID number; every data chunk within the file will contain this unique object ID within the spare area. YAFFS maintains a tree structure in RAM memory of the physical location of these1狗拿耗子chunks. When a chunk is no longer valid (the file is deleted, or parts of the file are overwritten), YAFFS marks a particular byte in the spare area of the chunk as ‘dirty’. When an entire block (32 pages) is marked as dirty, YAFFS can erase the block and reclaim the space. If free space on the device is low, YAFFS may need to choose a block that has some number of dirty pages and some number of good pages, move the good pages to a new block, mark the old pages as dirty and erase the block. The process of moving good pages & erasing blocks is called Garbage Collection. When a YAFFS system mounts a NAND flash device, it must scan the spare areas of every block to check for valid data, whereby it can then reconstitute the tree data structures. YAFFS2 YAFFS2 is similar in concept to YAFFS1, and shares much the same code; and the YAFFS2 code base supports YAFFS1 data formats through backward compatibility. The main difference is that YAFFS2 needs to jump through significant hoops to meet the "write once" requirement of modern NAND flash. YAFFS2 marks every newly written block with a sequence number that is monotonically increasing. The sequence of the chunks can be inferred from the block sequence number and the chunk offset within the block. Thereby when YAFFS2 scans the flash and detects multiple chunks that have identical ObjectIDs and ChunkNumbers, it can choose which to use by taking the greatest sequence number. For efficiency reasons YAFFS2 also introduces the concept of shrink headers. For example when a file is resized to a smaller size, YAFFS1 will mark all of the affected chunks as dirty - YAFFS2 cannot do this due to the "write once" rule. YAFFS2 instead writes a "shrink header", which indicates that a certain number of pages before that point are invalid. This lets YAFFS2 reconstruct the final state of the filesystem when the system reboots. YAFFS2 uses a more abstract definition of the NAND flash allowing it to be used with a wider variety of flash parts with different geometries, bad block handling rules etc. YAFFS2 now supports "checkpointing" which bypasses normal mount scanning, allowing very fast mount times. Mileage will vary, but mount times of c. 3 seconds for 2 GB have been reported.2狗拿耗子2、chunk 与 block K9F1208 是 64M 的 Nand Flash, 一个 chunk 包含 512byte 的 data area, 16byte 的 spare area, 与 32 个 chunk 构成了一个 block。
关于一篇yaffs2很好的文章
装置为硬碟及快闪记忆体(FlashMemory),虽然硬碟的容量相当大,但是其执行速度相当的慢、体积大且不耐震,较不适用于需要效率、体积及耐震考量的EmbeddedSystem,因为FlashMemory速度快,体积小及耐震的特性,大部份的EmbeddedSystem皆使用FlashMemory做为其内部储存装置。
如市面上最常见到的行动电话、PDA (PersonalDigitalAssistant)内部储存装置等或是数位相机所使用的记忆卡,皆使用FlashMemory。
因此该怎么操作或更有效率的使用FlashMemory,都是我们所要去关注的。
二、动机FlashMemory目前分为两种:NORFlashMemory及NANDFlashMemory,尤于NANDFlashMemory有较快的EraseTime、SmallSize及成本较低的特性下,使得NAND更适用于EmbeddedSystem。
FlashMemory是一储存装置,若要使用此储存装置,亦须要在FlashMemory上使用FileSystem。
在一般的BlockDevice(e.g.Disk)上使用的FileSystem,如:NTFS、FAT32和ext2等等,都可用于FlashMemory上,但是这些FileSystem并非专为Flash 所设计的,所以无针对Flash的特性去操作,因些需要透用FTL(FlashTranslationLayer)将其做转换的动作,如下图所示图一使用非专为Flash所设计的FileSystem(Flash-SpecificFileSystem),则需要透过FTL做转换,才能存取FlashMemory,但使用FTL会多了一个转换的过程,会浪费转换的时间,对于相当要求效率的EmbeddedSystem来说,不太适用,因此则有专为FlashMemory所设计(Flash-SpecificFileSystem)的FileSystem,如:JFFS、JFFS2和YAFFS等等。
yaffs第二篇——yaffs中的核心结构体
一个比较大的工程,最最核心的往往是数据结构体的定义,这是我最近一段时间啃yaffs啃出来的体会,一个复杂的函数往往是因为里面包含了各类结构体,结构体成员函数之间的不断转换,因此想要理解好一个大型的软件,一定要深刻的理解它的核心结构体。
话说有一天和trio一起吃饭,trio老师谈到他看代码的习惯,说往往是先不看.c 文件,先把头文件仔细读一遍,这点真是深刻啊!我的理解核心数据就像整个代码的经络一样,别看这个程序有多少多少万行代码,它本质上就是在对这些结构体进行操作。
废话少说,我们来看一下yaffs的核心结构体。
Y affs的主要的结构体在yaffs_guts.h这个文件中,核心的接头体有:struct yaffs_DeviceStructstruct yaffs_ObjectStructStruct yaffs_ObjectHeader//Struct yaffs_blockinfoStruct yaffs_spareStruct yaffs_tags//Struct yaffs_chunkcache还有一个比较重要的结构体在yaffs_fs.h这个文件中Struct yaffsfs_Handle当然还有其他很多结构体,这里先把主要的列在这儿,我准备从物理上和逻辑上因此可以这么来说实际和nandflash的硬件相关的结构体有三个,其他的结构体都是只是为了维护yaffs的组织目录而在内存中形成的。
所以,yaffs的整个目录是可以通过遍历整个yaffs的结构,读取spare区和object headler来得到yaffs中的所有逻辑结构。
这部分工作是在yaffs_mount这个函数来实现的,这个我们以后会继续讲到。
下面我们来详细讲解每个结构体:**************************NO 1************************************* struct yaffs_DeviceStruct{//一下是nandflash的属性,起始地址,结束地址,页大小,是否使用硬件ecc,缓冲的数量等int nBytesPerChu nk; // Should be a power of 2 >= 512int nChunksPerBlock; // does not need to be a power of 2int startBlock; // Start block we're allowed to useint endBlock; // End block we're allowed to useint nReservedBlocks; // We want this tuneable so that we can reduce// reserved blocks on NOR and RAM.int useNANDECC; // Flag to decide whether or not to use NANDECC int nShortOpCaches; // If <= 0, then short op caching is disabled, else// the number of short op caches (don't use too many).void *genericDevice; // Pointer to device context// On an mtd this holds the mtd pointer.// 以下是nandflash的操作函数,这些是直接和硬件相关,需要我们根据不同的处理器进行特定的处理,包括读,写,擦除,初始化int (*writeChunkToNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, const __u8 *data, yaffs_Spare *spare);int (*readChunkFromNAND)(struct yaffs_DeviceStruct *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare);int (*eraseBlockInNAND)(struct yaffs_DeviceStruct *dev,int blockInNAND);int (*initialiseNAND)(struct yaffs_DeviceStruct *dev);// Runtime parameters. Set up by Y AFFS.int internalStartBlock; // Internal version of startBlockint internalEndBlock; // End block we're allowed to useint blockOffset;int chunkOffset;__u16 chunkGroupBits; // 0 for devices <= 32MB. else log2(nchunks) - 16__u16 chunkGroupSize; // == 2^^chunkGroupBitsint isMounted;//以下是记录整个nandflash所有块信息的部分,在系统初始化的时候会为nandflash所有的块分配一个yaffs_blockinfo的信息结构体,它的首地址就是Blockinfoyaffs_BlockInfo *blockInfo;//chunkbits 和chunkBitmapStride是两个很有意思的东西,正是它们组成了整个nandflash的位图架构,对于一块有32页的nandflash,这里的chunkBitmapStride是4,而chunkbits是8位的,这样刚好4*8=32,也就是每一个位对应了nandflash中一个page,当然在系统挂载初始化的时候会为每一个块都分配,也就是说在首地址是chunkbits中的每一个位都对应了nandflash的一页,当然一个地址对应8页。
yaffs2文件系统工具mkyaffs2image
yaffs2⽂件系统⼯具mkyaffs2imageyaffs2⽂件系统是针对nandflash的⽂件系统,其制作⼯具为mkyaffs2image。
⼀、差异不同nand容量,⼯具不⼀样。
⾸先使⽤的是mkyaffs2image,编译⽣成根⽂件系统的镜像之后,下载到板⼦上,启动的时候报错,错误代码这⾥没有上传。
问题出在⼯具使⽤的不正确,查看⼯具⽬录下,发现有mkyaffs2image-128M⼯具,于是在⽹上查阅了⾸先采⽤的mkyaffs2image和mkyaffs2image-128M的区别,发现这对不同的板载nand flash容量,使⽤不同的⼯具制作根⽂件系统。
查看了⾃⼰使⽤的友善之臂板⼦上使⽤的nand flash是256M的,于是果断使⽤mkyaffs2image-128M⼯具制作根⽂件系统。
因为mkyaffs2image-128M针对128M或者更⼤的容量。
⼆、编译If you want to use GIT directly from the command line then public read-only access is available, using the (bash) command:git clone git:///yaffs2mkyaffs2image是在yaffs⽂件系统的utils⽬录下,只把其中的chunkSize spareSize 与 pagesPerBlock⼏个变量,按照nand_flash中的改⼀下就可以⽤。
// Adjust these to match your NAND LAYOUT://#define chunkSize 8192//#define spareSize 232#define chunkSize 4096//#define spareSize 218#define spareSize 128#define pagesPerBlock 128三、使⽤1、验证是否成功可直接在终端下输⼊:mkyaffs2imagemkyaffs2image: image building tool for YAFFS2 built Jul 92009usage: mkyaffs2image dir image_file [convert]dir the directory tree to be convertedimage_file the output file to hold the image'convert' produce a big-endian image from a little-endian machine注意核对convert的⼤⼩端。
基于NAND闪存的YAFFS2文件恢复技术研究
基于NAND闪存的YAFFS2文件恢复技术研究作者:范道睿李平安来源:《电子技术与软件工程》2016年第04期摘要随着经济及技术的迅猛发展,智能移动终端应用逐步普及,NAND闪存技术取得了长足的发展,基于NAND闪存的YAFFS2数据恢复技术显得日益重要。
本文主要从YAFFS2简介入手,重点对文件恢复技术进行了分析和阐述,并有针对性地进行模拟实验分析,以供同行参考。
【关键词】NAND 闪存 YAFFS2 文件恢复1 引言NAND闪存与以往磁存储器比较,其在硬件上具有耐擦写次数低且不支持异地存储等特点;在软件上则具有磨损均衡、按块擦写以及垃圾回收等特殊性能。
就目前而言,普遍使用的Android智能手机,其内核存储器采用的就是基于NAND闪存的YAFFS2数据恢复技术。
2 YAFFS2简介2.1 NAND闪存2.1.1 物理特性NAND拥有质量轻、功耗低、存储成本低等优势,常被用于手机、数码相机等移动设备领域。
同时,NAND闪存具有未被擦除和擦除两个状态,且属于非易失性存储器,即便是掉电后仍能够对内部存储数据加以保存。
2.1.2 逻辑结构由小到大,NAND闪存的逻辑结构依次排列为页、块、可擦除区域。
一般来说,块是可擦除的最小单位(由32或者64个页组成),多个可擦除块可以组成一个可擦除区域(256或者1024个块组成)。
每个NAND闪存的存储能力决定了其包含块的数目。
2.1.3 操作特性通常情况下,可在NAND闪存中分别进行对块擦除操作、写操作以及对单页面进行读操作等三种操作方式,其中以单页面读的操作速度最快。
同时,为有效延长NAND闪存的使用寿命,通常会使用磨损均衡机制。
2.2 YAFFS2文件系统就目前而言,1KB或者2KB页面大小的闪存为YAFFS2的主要服务对象。
加上当前NAND对一次性写入有着较高的要求,因此YAFFS2中已删除标志位已经被淘汰。
与传统的YAFFS1比较,YAFFS2具有较大的容量,且具有较为先进的文件存储方式。
yaffs2源代码分析
yaffs2源代码分析(一)yaffs2源代码情景分析作者:斑点Email: byeyear@1.前言略。
2.yaffs文件系统简介按理说这里应该出现一些诸如“yaffs是一种适合于NAND Flash的文件系统XXXXX”之类的字眼,不过考虑到网络上关于yaffs/yaffs2的介绍已经多如牛毛,所以同上,略。
3.本文内容组织本文将模仿《linux内核源代码情景分析》一书,以情景分析的方式对yaffs2文件系统的源代码进行分析。
首先将分析几组底层函数,如存储空间的分配和释放等;其次分析文件逻辑地址映射;然后是垃圾收集机制;接下来……Sorry,本人还没想好。
:-)4.说明因为yaffs2貌似还在持续更新中,所以本文所列代码可能和读者手中的代码不完全一致。
另外,本文读者应熟悉C语言,熟悉NAND Flash 的基本概念(如block和page)。
Ok,步入正题。
首先分析存储空间的分配。
5.NAND Flash存储空间分配和释放我们知道,NAND Flash的基本擦除单位是Block,而基本写入单位是page。
yaffs2在分配存储空间的时候是以page为单位的,不过在yaffs2中把基本存储单位称为chunk,和page是一样的大小,在大多数情况下和page是一个意思。
在下文中我们使用chunk这个词,以保持和yaffs2的源代码一致。
我们先看存储空间的分配(在yaffs_guts.c中。
这个文件也是yaffs2文件系统的核心部分):static int yaffs_AllocateChunk(yaffs_Device * dev, int useReserve,yaffs_BlockInfo **blockUsedPtr){int retVal;yaffs_BlockInfo *bi;if (dev->allocationBlock < 0) {/* Get next block to allocate off */dev->allocationBlock = yaffs_FindBlockForAllocation(dev);dev->allocationPage = 0;}函数有三个参数,dev是yaffs_Device结构的指针,yaffs2用这个结构来记录一个NAND器件的属性(如block和page的大小)和系统运行过程中的一些统计值(如器件中可用chunk的总数),还用这个结构维护着一组NAND操作函数(如读、写、删除)的指针。
yaffs2 结构
YAFFS2是一种常见的嵌入式文件系统,主要用于NAND闪存设备。
它具有许多优点,如支持大容量存储、快速读取、易于维护等。
YAFFS2文件系统的基本结构包括以下几个部分:
1.超级块(Super Block):超级块是文件系统的元数据,包含了文件系统的
基本信息,如文件系统的类型、大小、创建时间等。
2.块组(Block Group):块组是文件系统中的数据存储单元,由多个块组
成。
每个块组包含一个超级块和多个数据块。
3.数据块(Data Block):数据块是文件系统中的主要存储单元,用于存储文
件和目录的数据。
一个块组中可以有多个数据块,每个数据块包含一定数量的页面。
4.页面(Page):页面是数据块中的最小存储单元,用于存储文件系统中的实
际数据。
一个数据块中可以包含多个页面。
5.目录(Directory):目录用于存储文件和子目录的元数据,如文件名、文
件大小、创建时间等。
6.文件(File):文件是文件系统中的基本存储单元,用于存储用户数据。
一
个目录中可以包含多个文件和子目录。
嵌入式Linux下大容量Nand FLASH的YAFFS2文件系统构建
嵌入式Linux下大容量Nand FLASH的YAFFS2文件系统构建查启鹏;姚国良;张萌【期刊名称】《现代电子技术》【年(卷),期】2007(30)18【摘要】YAFFS2文件系统支持页大小为2 kB的大容量Nand FLASH和一些具有严格写入时序如零重写要求的Nand FLASH,是嵌入式系统中实现对Nand FLASH管理的理想方案.重点分析了YAFFS2相对于YAFFS1所做的两点重要改进,即垃圾回收策略和checkdata的引入,并介绍了Nand FLASH的硬件接口设计和MTD驱动编写方法,给出了Intel Xscale PXA255、Linux 2.4.19平台下,在页大小为2 kB的大容量Nand FLASH上构建YAFFS2的方法和过程.【总页数】4页(P55-58)【作者】查启鹏;姚国良;张萌【作者单位】东南大学,国家专用集成电路系统工程中心,江苏,南京,210096;东南大学,国家专用集成电路系统工程中心,江苏,南京,210096;东南大学,国家专用集成电路系统工程中心,江苏,南京,210096【正文语种】中文【中图分类】TP311【相关文献】1.超大容量NAND Flash文件系统-YAFFS2在Linux下的实现 [J], 龙亚春;黄璞;吴胜2.Yaffs2文件系统中对NAND Flash磨损均衡的改进 [J], 温朝建;严华3.在Linux中实现大容量NAND Flash的YAFFS2文件系统 [J], 展中华;杜刚4.嵌入式Linux下NAND flash上根文件系统的构建 [J], 程建5.Yaffs2文件系统中NAND Flash块选择策略的改进 [J], 杨智;严华因版权原因,仅展示原文概要,查看原文内容请购买。
struts2源代码分析(个人觉得非常经典)
本章讲述Struts2的工作原理。
读者如果曾经学习过Struts1.x或者有过Struts1.x的开发经验,那么千万不要想当然地以为这一章可以跳过。
实际上Struts1.x与Struts2并无我们想象的血缘关系。
虽然Struts2的开发小组极力保留S truts1.x的习惯,但因为Struts2的核心设计完全改变,从思想到设计到工作流程,都有了很大的不同。
Struts2是Struts社区和WebWork社区的共同成果,我们甚至可以说,Struts2是WebWork的升级版,他采用的正是WebWork的核心,所以,Struts2并不是一个不成熟的产品,相反,构建在We bWork基础之上的Struts2是一个运行稳定、性能优异、设计成熟的WEB框架。
本章主要对Struts的源代码进行分析,因为Struts2与WebWork的关系如此密不可分,因此,读者需要下载xwork的源代码,访问即可自行下载。
下载的Struts2源代码文件是一个名叫struts-2.1.0-src.zip的压缩包,里面的目录和文件非常多,读者可以定位到struts-2.1.0-src"struts-2.0.10"src"core"src"main"java目录下查看Struts2的源文件,如图14所示。
(图14)主要的包和类Struts2框架的正常运行,除了占核心地位的xwork的支持以外,Struts2本身也提供了许多类,这些类被分门别类组织到不同的包中。
从源代码中发现,基本上每一个Struts2类都访问了WebWork提供的功能,从而也可以看出Struts2与WebWork千丝万缕的联系。
但无论如何,Struts2的核心功能比如将请求委托给哪个Action处理都是由xwork完成的,Struts2只是在WebWork的基础上做了适当的简化、加强和封装,并少量保留Struts1.x中的习惯。
YAFFS2文件系统
1 Yaffs文件系统结构1.1 简介1.1.1应用场合Yaffs(Yet Another Flash File System)文件系统是专门针对NAND闪存设计的嵌入式文件系统,目前有YAFFS和YAFFS2两个版本,两个版本的主要区别之一在于YAFFS2能够更好的支持大容量的NAND FLASH芯片。
Yaffs文件系统有些类似于JFFS/JFFS2文件系统,与之不同的是JFFS1/2文件系统最初是针对NOR FLASH的应用场合设计的,而NOR FLASH和NAND FLASH本质上有较大的区别,所以尽管JFFS1/2 文件系统也能应用于NAND FLASH,但由于它在内存占用和启动时间方面针对NOR的特性做了一些取舍,所以对NAND来说通常并不是最优的方案。
1.1.2NOR和NAND的比较基本上NOR比较适合存储程序代码,其容量一般较小(比如小于32MB),价格较高,而NAND容量可达1GB以上,价格也相对便宜,适合存储数据。
一般来说,128MB以下容量NAND FLASH 芯片的一页大小为528字节,用来存放数据,另外每一页还有16字节的备用空间(SpareData,OOB),用来存储ECC校验/坏块标志等信息,再由若干页组成一个块,通常一块为32页16K。
与NOR相比,NAND不是完全可靠的,每块芯片出厂时都有一定比例的坏块存在,对数据的存取不是使用地址映射而是通过寄存器的操作,串行存取数据。
1.2 Yaffs文件系统数据在NAND上的存储方式Yaffs对文件系统上的所有内容(比如正常文件,目录,链接,设备文件等等)都统一当作文件来处理,每个文件都有一个页面专门存放文件头,文件头保存了文件的模式、所有者id、组id、长度、文件名、Parent Object ID等信息。
因为需要在一页内放下这些内容,所以对文件名的长度,符号链接对象的路径名等长度都有限制。
前面说到对于NAND FLASH上的每一页数据,都有额外的空间用来存储附加信息,通常NAND驱动只使用了这些空间的一部分,Yaffs正是利用了这部分空间中剩余的部分来存储文件系统相关的内容。
深入理解yaffs2文件系统(一)
深入理解yaffs2文件系统(一)1、Flash文件系统1.1、背景已经有多种flash文件系统(FFSs)或flash块驱动(在之上运行一个常规的FS),同时都有优点或缺点。
Flash存储器有非常多的限制,这里就不一一列举了。
已经有各种方法解决这些限制,以提供一个文件系统。
必须认识到,“flash”,包括NOR和NAND,各自有不同的限制。
很容易被专业术语“flash”误导,误以为用于NorFlash的方法也立即适用于NandFlash。
Nand块驱动一般采用FAT16作为文件系统,但不够健壮,也不够贴近Flash的特性。
这些块驱动通过一个“本地--物理”的映射层来仿真可写的、类似于磁盘扇区的块。
当使用FAT16时,这些文件系统工作的相当好,它们内存消耗小,代码尺寸也很小。
但就像所有基于FAT 的系统一样,它们很容易损坏(如,丢失簇)。
其他的途径则是设计整个文件系统,不是基于块驱动,而且是flash友好的,这允许更多的余地来解决上述所提到的问题。
当前有两个linux文件系统能非常好的支持NorFLash,那就是JFFS以及它的升级版本JFFS2。
这两者都提供日志机制,大大的提升了健壮性,这也是嵌入式系统特别重要的一个特性。
不幸的是,它们在RAM消耗和启动时间方面都不是很好。
JFFS在flash中的每一个journalling日志节点,需要一个基于RAM的jffs_node结构,每一个节点为48字节。
JFFS2做了一个大改进,通过剪裁相关的结构体(jffs2_raw_node_ref)而减少到16字节。
即使如此,在512字节页大小128M的NandFlash,按平均节点大小来算,也需要250000字节约4M大小。
JFFS和JFFS2在启动时,需要扫描整个flash阵列来查找journaling节点,并决定文件结构。
由于NAND容量大、慢、连续访问、需要ECC校验,这些特性将导致不可接受的、很长的启动时间。
yaffs2 结构 -回复
yaffs2 结构-回复YAFFS2 结构YAFFS2(Yet Another Flash File System 2)是一种用于嵌入式系统的文件系统,特别适用于闪存设备。
它的灵感来自于早期的YAFFS文件系统,但在架构和功能上有所改进。
YAFFS2提供了高效的数据存储和管理方式,使闪存设备在读写操作方面更加稳定和可靠。
YAFFS2的主要结构包括:块(Block)、页(Page)、幸存页(Spare Page)和节点(Node)。
首先,让我们从块开始。
块是YAFFS2中最小的存储单元,它由连续的页组成。
每个块的大小通常为128KB或256KB。
闪存设备的数据存储是以块为单位进行的,这意味着当我们需要存储一个文件或一个数据块时,实际上是将其存储到一个或多个连续的块中。
在每个块中,数据被分为多个页。
每个页的大小通常为2KB或4KB。
这样的设计使得YAFFS2能够更高效地进行读写操作,因为闪存设备的读写速度是以页为单位的。
幸存页是指在每个块中用于存储元数据的页。
元数据包括节点、标志位、CRC等信息。
幸存页的存在使得YAFFS2能够更好地管理闪存设备的使用情况,并使得数据的读写更加可靠。
最后,我们来看一下节点。
节点对于YAFFS2来说非常重要,它是文件系统中的基本单位。
每个节点对应着一个文件或目录。
节点存储了文件的元数据,如文件名、文件大小、文件权限等。
除此之外,节点还存储了指向文件数据在闪存设备上位置的指针。
通过以上的结构,YAFFS2实现了对闪存设备的高效管理和读写。
当我们在闪存设备上创建一个文件时,YAFFS2会为该文件创建一个对应的节点,并将其相关信息存储在该节点中。
当我们写入数据时,YAFFS2将数据分为页,并将这些页存储在连续的块中。
为了保证数据的完整性,YAFFS2还会计算并存储CRC等校验信息。
在读取数据时,YAFFS2会通过节点找到数据的位置,并将其读取到应用程序中。
此外,YAFFS2还具备一些高级功能,如快照(Snapshot)和压缩(Compression)。
yaffs2文件系统实现原理分析_带书签
1 概述YAFFS (Yet Another Flash File System )文件系统是专门针对NAND flash 设计的嵌入式文件系统,目前有YAFFS 和Y AFFS2两个版本,两个版本的主要区别之一在于Y AFFS2 能够更好的支持大容量的NAND flash 芯片。
YAFFS 文件系统有些类似于JFFS/JFFS2文件系统,与之不同的是JFFS/JFFS2文件系统最初是针对NOR flash 的应用场合设计的,而NORflash 和NAND flash 本质上有较大的区别,尽管JFFS/JFFS2文件系统也能应用于NANDflash ,但由于它在内存占用和启动时间方面针对NOR 的特性做了一些取舍,所以YAFFS2对NAND flash 来说通常才是最优的选择方案。
2 相关概念分析YAFFS2之前,把NAND flash 相关概念介绍下:NAND flash 由块(block)组成,块又由页(page)构成,擦除时以块为单位,读写时以页为单位,页又包含数据区和空闲区(OOB,Out-Of-Band),而Page 在YAFFS2中被称为Chunk ,其中的数据区用来存放实际的数据,OOB 用来存放附加信息实现NAND flash 的管理。
以T8000 AXMPFUA 单板使用的NANDflash 为例,每块Block: 128 pages ,每页Page: (8K + 448) bytes ,数据区为8K ,OOB 为448bytes ,如图1所示:Plane :4096blocks128 pages(8K+448)bytes图1 NAND flash 物理结构3 数据结构struct yaffs_dev 是YAFFS2文件系统最核心的数据结构,表示Y AFFS2文件系统的超级块,它建立了整个文件系统的层次结构,并衔接VFS 层和MTD 层,与struct super_block 、struct mtd_info 的关系如图2所示:图2 yaffs_dev与super_block、mtd_info层次关系下面围绕struct yaffs_dev这个最核心的数据结构开始,分段介绍它的含义,进而引出其他重要的数据结构:■param:存储文件系统重要的一些参数,以及与MTD层的接口函数□inband_tags:标志位,默认为0,即采用OOB(out of band)方式存储tags,可以通过挂载时指定inband-tags选项改变默认值□total_bytes_per_chunk:每个chunk总的字节数□chunks_per_block:每个block总的chunk数□spare_bytes_per_chunk:每个chunk包含OOB块的字节数□start_block:第一个可以使用的block□end_block:最后一个可以使用的block□n_reserved_blocks:为GC保留的block阈值□n_caches:缓冲区的个数,YAFFS2为减少数据的碎片以及提高性能为每个文件的写入提供了cache□no_tags_ecc:标志位,默认为0,即tags中包括ECC纠错信息,可以通过内核配置改变默认值,CONFIG_YAFFS_DISABLE_TAGS_ECC□is_yaffs2:标志位,默认为0,即Y AFFS,在挂载的过程中会根据识别的mtd->writesize自动转换成YAFFS2□refresh_period:刷新周期,刷新目的主要找出最旧的处于YAFFS_BLOCK_STATE_FULL状态的block,供GC作为gc_block使用□skip_checkpt_rd:标志位,默认为0,支持读取checkpoint,提高挂载速度的一个功能可以通过挂载时指定挂载选项no-checkpoint-read、no-checkpoint修改默认值□skip_checkpt_wr:标志位,默认为0,支持写入checkpoint,提高挂载速度的一个功能可以通过挂载时指定挂载选项no-checkpoint-write、no-checkpoint修改默认值□write_chunk_tags_fn:函数指针,在挂载的文件系统的时候会被初始,NANDflash写入接口函数:param->write_chunk_tags_fn = nandmtd2_write_chunk_tags;□read_chunk_tags_fn:函数指针,在挂载的文件系统的时候会被初始,NANDflash读取接口函数:param->write_chunk_tags_fn = nandmtd2_write_chunk_tags;□erase_fn:函数指针,在挂载的文件系统的时候会被初始,NAND flash擦除block接口函数:param->erase_fn = nandmtd_erase_block;□wide_tnodes_disabled:标志位,默认值为0,采用动态位宽,通过内核配置修改可采用静态位宽CONFIG_YAFFS_DISABLE_WIDE_TNODES■os_context:指向yaffs_linux_context结构指针,该结构存储Y AFFS2运行环境,如下:□context_list:通过该字段加入到yaffs_context_list全局链表中□dev:指向Y AFFS2文件系统超级块的指针□super:指向VFS层超级块的指针□bg_thread:Y AFFS2后台垃圾回收线程的指针□bg_running:启动和停止垃圾回收线程的标志位,1:启动,0:停止□gross_lock:互斥锁,保护整个超级块关键字段的互斥访问,粒度比较大□spare_buffer:OOB块的缓冲区□search_contexts:通过该字段把所有Directory Search Context组成链表□yaffs_mtd_put_super:卸载文件系统时被调用来清理super_block□readdir_process:解决使用NFS死锁问题加入的□mount_id:每个NAND flash分区挂载YAFFS2都分配不同的ID号■driver_context:指向mtd_info结构指针,mtd_info是MTD子系统核心的数据结构,主要是对底层硬件驱动进行封装,这里不再介绍■data_bytes_per_chunk:每个chunk总的字节数,和前面提到的total_bytes_per_chunk一样■chunk_grp_bits :采用静态位宽时超过tnode_width宽度之后的位数,采用动态位宽值恒为0■chunk_grp_size:由chunk_grp_bits转化而来的大小■tnode_width:采用静态位宽默认是16,采用动态位宽是由整个NAND flash中chunk数目计算得到■tnode_mask:位宽的mask,主要用于快速获取chunk id号■tnode_size:YAFFS_NTNODES_LEVEL0节点所占用的内存大小,单位:byte■chunk_shift:主要用来计算logical chunk index以及logical chunk offset■chunk_div:作用同chunk_shift,主要用于chunk大小不是2次幂的情况■chunk_mask:作用同chunk_shift,组合起来计算logical chunk offset■is_mounted:标志位,文件系统挂载时被置位Checkpoint是为提高挂载速度而引入的功能,作用同JFFS2的EBS,以空间来换取时间,卸载时通过在NAND flash上保存文件系统超级块快照,挂载时获取快照信息可以快速还原系统的状态。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
5.NAND Flash 存储空间分配和释放 我们知道,NAND Flash 的基本擦除单位是 Block,而基本写入单位是 page。yaffs2 在分配 存储空间的时候是以 page 为单位的,不过在 yaffs2 中把基本 存储单位称为 chunk,和 page 是一样的大小,在大多数情况下和 page 是一个意思。在下文中我们使用 chunk 这个 词,以保持和 yaffs2 的源代 码一致。 我们先看存储空间的分配(在 yaffs_guts.c 中。这个文件也是 yaffs2 文件系统的核心部分):
[yaffs_AllocateChunk() => yaffs_FindBlockForAllocation()] static int yaffs_FindBlockForAllocation(yaffs_Device * dev) { int i; yaffs_BlockInfo *bi; if (dev->nErasedBlocks < 1) { /* Hoosterman we've got a problem. * Can't get space to gc */ T(YAFFS_TRACE_ERROR, (TSTR("yaffs tragedy: no more eraased blocks" TENDSTR))); return -1; } dev->nErasedBlocks 记录着器件内所有可供分配的 block 的数量。如果该值小于 1,那显 然是有问题了。不但正常的分配请求无法完成,就连垃圾收集都办不到了。 for (i = dev->internalStartBlock; i <= dev->internalEndBlock; i++) { dev->allocationBlockFinder++; if (dev->allocationBlockFinder < dev->internalStartBlock || dev->allocationBlockFinder > dev->internalEndBlock) { dev->allocationBlockFinder = dev->internalStartBlock; internalStartBlock 和 internalEndBlock 分别是 yaffs2 使用的 block 的起始序号和结束 序号。也就是说 yaffs2 文件系统不一定要占据整个 Flash,可以只占用其中的一部分。 dev->allocationBlockFinder 记录着上次分配的块的序号。如果已经分配到系统尾部,就 从头重新开始搜索可用块。 bi = yaffs_GetBlockInfo(dev, dev->allocationBlockFinder); if (bi->blockState == YAFFS_BLOCK_STATE_EMPTY) { bi->blockState = YAFFS_BLOCK_STATE_ALLOCATING; dev->sequenceNumber++;
bi->sequenceNumber = dev->sequenceNumber; dev->nErasedBlocks--; T(YAFFS_TRACE_ALLOCATE, (TSTR("Allocated block %d, seq %d, %d left" TENDSTR), dev->allocationBlockFinder, dev->sequenceNumber, dev->nErasedBlocks)); return dev->allocationBlockFinder; } yaffs_GetBlockInfo 函数获取指向 block 信息结构的指针,该函数比较简单,就不详细介 绍了。yaffs_BlockInfo 结构中的 blockState 成员描述该 block 的状态,比如空,满,已 损坏,当前分配中,等等。因为是要分配空闲块,所以块状态必须是 YAFFS_BLOCK_STATE_EMPTY,如果不是,就继续测试下一个 block。找到以后将 block 状 态修改为 YAFFS_BLOCK_STATE_ALLOCATING,表示当前正从该 block 中分配存储空间。正 常情况下,系统中只会有一个 block 处于该状 态。另外还要更新统计量 ErasedBlocks 和 sequenceNumber。这个 sequenceNumber 记录着各 block 被分配出去的先后 顺序,以后在 垃圾收集的时候会以此作为判断该 block 是否适合回收的依据。 现在让我们返回到函数 yaffs_AllocateChunk 中。yaffs_CheckSpaceForAllocation()函数 检查 Flash 上是否有足够的可用空间,通过检查后,就从当前供分配的 block 上切下一个 chunk: if (dev->allocationBlock >= 0) { bi = yaffs_GetBlockInfo(dev, dev->allocationBlock); retVal = (dev->allocationBlock * dev->nChunksPerBlock) + dev->allocationPage; bi->pagesInUse++; yaffs_SetChunkBit(dev, dev->allocationBlock, dev->allocationPage); dev->allocationPage++; dev->nFreeChunks--; /* If the block is full set the state to full */ if (dev->allocationPage >= dev->nChunksPerBlock) { bi->blockState = YAFFS_BLOCK_STATE_FULL; dev->allocationBlock = -1; } if(blockUsedPtr) *blockUsedPtr = bi; return retVal; } dev->allocationPage 记录着上次分配的 chunk 在 block 中的序号,每分配一次加 1。从这 里我们可以看出,系统在分配 chunk 的时候是从 block 的开头到结尾按序分配的,直到一 个 block 内的所有 chunk 全部分配完毕为止。retVal 是该 chunk 在整个 device 内的总序 号。PagesInUse 记录着该 block 中已分配使用的 page 的数量。
if (bi->blockState == YAFFS_BLOCK_STATE_ALLOCATING || bi->blockState == YAFFS_BLOCK_STATE_FULL || bi->blockState == YAFFS_BLOCK_STATE_NEEDS_SCANNING || bi->blockState == YAFFS_BLOCK_STATE_COLLECTING) { dev->nFreeChunks++; yaffs_ClearChunkBit(dev, block, page); bi->pagesInUse--; if (bi->pagesInUse == 0 && !bi->hasShrinkHeader && bi->blockState != YAFFS_BLOCK_STATE_ALLOCATING && bi->blockState != YAFFS_BLOCK_STATE_NEEDS_SCANNING) { yaffs_BlockBecameDirty(dev, block); } } else { /* T(("Bad news deleting chunk %d\n",chunkId)); */ } 首先要判断一下该 block 上是否确实存在着可释放的 chunk。block 不能为空,不能是坏块。
系统在设备描述结构 yaffs_Device 中维护着一张位图,该位图的每一位都代表着 Flash 上的一个 chunk 的状态。yaffs_SetChunkBit()将刚分配得到的 chunk 在位图中的对应位置 1,表明该块已被使用。更新一些统计量后,就可以返回了。
看过 chunk 分配以后,我们再来 chunk 的释放。和 chunk 分配不同的是,chunk 的 释放在大多数情况下并不释lock 擦除,所以物理介质的释放要留到垃圾收集或一个 block 上的所有 page 全部 变成空闲的时候才进行。 根据应用场合的不同,chunk 的释放方式并不唯一,分别由 yaffs_DeleteChunk 函数和 yaffs_SoftDeleteChunk 函数完 成。我们先看 yaffs_DeleteChunk:
chunk 的总数),还用这个结构维护着一组 NAND 操作函数(如读、写、删除)的指针。 整个结构体比较大,我 们会按情景的不同分别分析。useReserve 表示是否使用保留空间。 yaffs2 文件系统并不会将所有的存储空间全部用于存储文件系统数据,而要空出 部分 block 用于垃圾收集时使用。一般情况下这个参数都是 0,只有在垃圾收集时需要分配存 储空间的情况下将该参数置 1。yaffs_BlockInfo 是描述 block 属性的结构,主要由一些统 计变量组成,比如该 block 内还剩多少空闲 page 等。我们同样在具体情景中再分析这个结 构中的字段含义。 函数首先判断 dev->allocationBlock 的值是否小于 0。yaffs_Device 结构内的 allocationBlock 字段用于 记录当前从中分配 chunk(page)的那个 block 的序号。当一 个 block 内的所有 page 全部分配完毕时,就将这个字段置为-1,下次进入该函 数时就会 重新挑选空闲的 block。这里我们假定需要重新挑选空闲 block,因此进入 yaffs_FindBlockForAllocation 函数: