UBIFS文件系统说明文档.docx

上传人:3399888 文档编号:1829664 上传时间:2020-10-23 格式:DOCX 页数:13 大小:43.08KB
下载 相关 举报
UBIFS文件系统说明文档.docx_第1页
第1页 / 共13页
UBIFS文件系统说明文档.docx_第2页
第2页 / 共13页
UBIFS文件系统说明文档.docx_第3页
第3页 / 共13页
UBIFS文件系统说明文档.docx_第4页
第4页 / 共13页
UBIFS文件系统说明文档.docx_第5页
第5页 / 共13页
点击查看更多>>
资源描述

1、UBIFS文件系统说明文档注意:在了解UBIFS之前一定要注意到UBIFS和任何传统的文件系统是不一样的:UBIFS不是运行在block device之上的(如hard disk,MMC/SD卡,USB flash等)。UBIFS是运行于raw flash之上,请在开始认识UBIFS前确保理解raw flash这个概念。UBIFS是建立在MTD device基础上的,而不是block device上的。简介:UBIFS是由NOKIA工程师在赛格德大学帮助下开发的新的Flash文件系统,UBIFS是JFFS2文件系统的下一代产品。JFFS2运行在MTD设备之上,而UBIFS则只能工作于UBI v

2、olume之上。UBIFS涉及三个子系统:1.MTD子系统,提供对Flash芯片的访问接口,MTD子系统提供了MTD 设备的概念,比如/dev/mtdx,MTD可以认为是raw flash。2.UBI子系统,为Flash设备提供了耗损均衡(wear leveling)和卷管理(volume management)功能; UBI工作在MTD设备之上,提供了UBI volume;UBI是MTD设备的高层次表示,对上层屏蔽了一些直接使用MTD设备需要处理的问题,比如损耗均衡以及坏块管理。3.UBIFS文件系统,工作于UBI之上的文件系统。UBIFS的主要特点:1.可扩展性:UBIFS对Flash 尺

3、寸有着很好的扩展性,也就是说mount时间,内存消耗以及I/O速度都不依赖于Flash 的尺寸,UBIFS可以很好的运行在GB级的 Flashe设备上,当然UBI本身还是有扩展性的问题,但是无论如何UBI/UBIFS都比JFFS2的可扩展性好。如果UBI成为瓶颈,可以改进UBI而不需改变UBIFS本身。2.快速mount:不像JFFS2文件系统,UBIFS在mount阶段不需要扫描整个文件系统,UBIFS mount的时间只是毫秒级,时间不依赖与Flash的尺寸;然而UBI的初始化时间是依赖Flash的尺寸的,因此必须把这个时间考虑在内。3.write back支持:回写或者延迟写,与JFFS

4、2文件系统的立即写入内存(write through)相比可以显著的提高文件系统的吞吐量。4.异常unmount适应度:UBIFS是日志文件系统,可以容忍突然掉电以及unclean重启; UBIFS通过replay日志来恢复unclean unmount。在这种情况下replay会消耗一些时间,因此mount时间会稍微增加,但是replay过程并不会扫描整个Flash介质,所以UBIFS的异常mount时间大概在几分之一秒。5.快速I/O操作:即使我们不使能 write back(在unmount时使用-o sync mount选项), UBIFS的性能仍然接近JFFS2;JFFS2的同步I/

5、O是非常惊人的,因为JFFS2不需要在flash上维护indexing data结构,所以就没有因此而带来的负担,而UBIFS恰恰是有index数据的,UBIFS之所以够快是因为UBIFS提交日志的方式:不是把数据从一个地方移动到另外一个位置,而只是把数据的地址加到文件系统的index,然后选择不同的eraseblock作为新的日志块,此外还有multi headed日志方式等技巧。6.On the flight compression:存储在Flash介质上的数据是压缩的,同时也可以灵活的针对单个文件来打开关闭压缩。例如,可能需要针对某个特定的文件打开压缩;或者可能缺省方式下支持压缩,但是对

6、多媒体文件则关闭压缩。7.可恢复性:UBIFS可以从index破坏后恢复; UBIFS中的每一片信息都用一个header来描述,因此可以通过扫描整个Flash介质来重构文件系统,这点和JFFS2非常类似。想像如果你擦除FAT文件系统的FAT表,对于FAT文件系统来说是致命的错误,但是如果擦除UBIFS的index,你仍然可以重构文件系统,当然这需要使用一个用户空间程序来做恢复8.完整性:UBIFS通过把checksum写到flash 介质上来保证数据的完整性,UBIFS不会无视损坏的文件数据或meta data;缺省的情况,UBIFS仅仅检查meta data的CRC,但是你可以通过mount

7、选项,强制进行data CRC的检查。UBIFS的可扩展性UBIFS文件系统的所有数据结构都是使用tree,UBIFS对flash尺寸大小在算法上是可扩展的。然而UBI复杂度随着Flash size线性增长,因此UBI加UBIFS整体上是线性增大的。但是UBIFS的作者认为可以创建一个新的UBI2,克服当前UBI的线性增长,当前的 UBI实现适和216GiB大小的raw flashes,具体大小依赖于I/O速度和系统需求。注意:尽管UBI是线性增长的,但是它的可扩展性依然好过JFFS2,因为JFFS2最初是为32MiB Nor flashes设计的。JFFS2的扩展性问题是文件系统级的,而UB

8、I/UBIFS的扩展性问题则是raw flash级的。UBIFS对回写操作的支持UBIFS支持write back, 意味着文件的改变并不是立刻提交到flash media上,而是cache这些修改,直到达到写入的条件,这减少了I/O的数目因此改善I/O性能和系统性能。回写本身也是文件系统的标准技术,由于数据没有立刻写入flash, 回写带来了数据丢失的风险。相反JFFS2不支持write back, JFFS2文件系统的所有变化都是立刻同步到flash介质上。事实上,JFFS2有一个很小的buffer大小是NAND page size(如果是 NAND flash),这个buffer保存这最

9、后要写的数据,一旦buffer写满立刻就会执行flush。 因此JFFS2非常类似于同步文件系统。Write back支持,需要应用程序注意及时同步重要的文件。否则掉电会导致这些文件的损坏和消失,掉电对于嵌入式系统而言是很常见的。然而一些应用空间程序并没有考虑write back这种情况,当这些应用运行在JFFS2上工作良好尽管这些应用是buggy的,一旦运行在UBIFS上,bugs就很容易重现了。所以在把JFFS2换作UBIFS后,确保检查你的应用是否正确处理掉电功能。下列是检查列表以及一些建议,这些方法对于任何文件系统都是可行的,包括JFFS2文件系统:1.如果你想切换到同步模式,在mou

10、nt文件系统是使用 -o 同步选项。然而,要注意文件系统将会下降。此外,要记住UBIFS mount为同步模式仍然不如JFFS2提供更多的保证。2.一定要时刻记住运行fsync在你修改重要数据后;当然,没有必要sync临时的文件;要先考虑文件数据的重要性,不要执行没必要的fsync,因为fsync操作会降低性能。3.如果你想更精确些,那么就使用fdatasync,仅仅修改的数据被flushed,而inode meta data变化不会被flush(比如mtime或者permissions)。4.你也可以在open()调用时使用O_SYNC标志;这使得这个文件所修改的data(不包括meta d

11、ata)都会在write()操作返回前写入media。通常最好使用fsync(),而且fsync允许多个累积的写。5.还可以使一定数目inodes为同步模式,通过设置inode的sync标志;在shell脚本中执行chattr +S;在C程序中,则可以使用FS_IOC_SETFLAGS ioctl命令;注意,mkfs.ubifs工具会检查原始的FS树,如果文件在原始文件树是同步的,那么在UBIFS image也会是同步的。fsync()可能包括目录,它同步目录inode的meta-data。sync flag也可以用在目录上,使得目录inode变成同步的。但是sync flag是可继承的,意味

12、这这个目录下的所有新节点都有这个标志,这个目录的新文件和新子目录也就变成同步的,子目录的child也是如此。这个功能对于创建一个整个目录树都同步的目录是很有用的。fdatasync()调用对 UBIFS的目录是不起作用的,因为UBIFS对目录项的操作都是同步的,当然不是所有文件系统都如此。dirsync inode 标志对UBIFS也没有作用。以上提到的功能都是作用于文件描述符,而不是文件stream(FILE *)。同步一个stream,你应该通过libc的fileno()取得文件描述符,首先使用fflush()来flush stream ,然后调用fsync或者fdatasync。你也可以

13、使用其他的同步方法,但是记得在同步文件之前要先flush stream,fflush() 和sync(),fsync,fdatasync与前者的区别,在于前者仅仅同步libc-level的buffer,而后者则是同步kernel level buffers。回写操作在LINUX中的控制Linux有几个内核参数可以用来调整write back,可查看/proc/sys/vm。这些参数是global, 所以会影响所有的文件系统。1.dirty_writeback_centisecs:linux周期性write back线程写出dirty数据的周期,这个机制可以确保所有的脏数据在某个时间点都可以写入

14、介质。2.dirty_expire_centisecs:dirty数据的过期周期,这是数据为dirty的最大时间。过了这个时间,dirty数据会被周期性write back线程写回介质。换句话说,周期性write back线程每dirty-writeback-centisecs 时间唤醒,然后同步那些dirty_expire_centisecs时间之前就已经dirty的数据。3.dity_background_ratio:dirty数据与全部内存的最大百分比。当脏数据变多的时候,周期性的write back线程开始同步数据使得脏数据比例变小。这个过程包括那些non-expired的数据。 这个

15、可以认为是系统dirty数据的soft limit。4.dirty_ratio:dirty数据与全部内存的最大百分比,超过这个显示,写同步数据先于增加dirty数据,这个是系统diry 数据的hard limit。UBIFS写缓存区UBIFS是一个异步文件系统,UBIFS利用了page cache。page cache是一个通用的linux内存管理机制,page cache可以非常大以缓存更多的数据。当你写一个文件时,首先写到page cache中,置为dirty,然后write操作返回(同步的文件是例外),然后数据会通过write back机制回写。Write buffer是UBIFS特定的

16、buffer,它位于page cache和flash介质之间。这意味着write buffer 只是写到write buffer上而不是flash介质。Write buffer是用来优化UBIFS在NAND flashes上的速度。NAND flashes包含NAND pages,页是NAND flash的最小读写单位,通常为512, 2KiB或者4KiB。Write buffer尺寸等于NAND page size。他的目的是积累samll writes为一个满的或者部分满的page。考虑下面的例子,假定在半秒内写了4x512bytes nodes,page size是2kiB的情况下,如果

17、没有write buffer,那么分开的写会使用4个page,浪费6KiB的空间,而write buffer 可以仅写一次,并且没有空间浪费。所以write buffer避免生成过多的dirty space,UBIFS的垃圾收集所做的工作就越少。当然上面的例子是一个理想状态,即便write buffer也可能浪费空间,比如使用同步I/O或者数据抵达的时间间隔较大。因为write buffer也有个过期时间,每3-5秒即便write buffer不满,也会写出,这是为了数据完整性的原因。当然,如果UBIFS写大量的数据,那么就不使用write buffer,仅仅数据的最后一部分由于小于NAND

18、page尺寸需要等待填满page的数据,直到write buffer的定时器到时。Write buffer实现上有一点复杂,UBIFS中使用了一些write buffer,每个journal head都有一个,当然这并不改变write buffer的基本机制。关于同步有几点需要注意的:1.sycn()会同步所有的write buffers。2.fsync(fd)也会同步 fd相关的所有write buffers。3.用O_SYNC打开文件,会忽略write buffers,所以I/O会直接写入介质。4.如果文件系统mount时使用了-o sync选项,那么write buffers也会被忽略。

19、数据同步时要考虑write buffer的timer时间,在dirty_expire_centisecs(同步时间)加上额外的3-5秒,当然由于write buffer很小,所以delay的数据很少。UBIFS同步模式 vs JFFS2同步模式Mount UBIFS文件系统使用-o sync标志,所有文件系统的操作都变成了同步模式,意味着在文件系统操作返回前,所有的数据都写入了flash存储介质中。例如,如果你使用write()写10MB数据到文件f.data,并且UBIFS是同步模式的。在write操作返回前所有的10M文件数据以及meta data(file size, date chan

20、ges)也写入了flash介质。此时即便掉电,这个文件的数据也会包含所有的10MB数据。在打开文件时,使用O_SYNC标志也有同样的效果。在突然掉电的情况下,UBIFS并不能像JFFS2那样提供较多的保证,在JFFS2中所有的meta data存储在data node headers中,数据节点包含4KiB的压缩数据。这意味meta data信息在flash有多个版本,每次JFFS2写一个data node到flash介质上时,都会更新文件的inode size。当JFFS2 mount时,会扫描flash介质,发现最后的data node,同时获取inode的size。在实际使用中,JFFS

21、2会顺序的写这10M数据,从头到尾。如果中间发生掉电,那么就丢失掉结尾的数据。也就是说如果写10M的数据到JFFS2中,写了5M,此时掉电发生,那么可以得到一个5MB的文件,而丢掉了未写入的5MB。对于UBIFS来说有一点点复杂,数据被存储在data nodes中,而meta data被存储在分离的inode nodes中。Meta data在每个数据节点中没有像JFFS2一样有duplicated的版本。UBIFS从来不会写on flash inode size外的数据节点。如果不得不写data node, 并且data node是在on flash inode size之外(in memo

22、ry inodes已经更新为up-to-data尺寸,但是脏的还没更新到flash上),那么UBIFS首先要把inode写入介质,然后才能开始写数据,此时掉电就可能会产生holes文件,看下面的例子1.用户创建一个空文件f.dat. 文件是同步的或者UBIFS文件系统被mount为同步模式。user调用write()函数来写一个10MB buffer.2.kernel首先拷贝所有的10MB数据到page cache。inode size 被修改为10MB并且inode被mark为dirty。没有任何数据和meta data写入flash media,此时如果发生掉电,那么user看到的是一个空

23、文件f.data。3.UBIFS看到I/O是同步的,那么首先开始同步inode,首先写inode node 到flash media中,此时如果发生掉电,那么user会看到一个10MiB大小的空文件。4. UBIFS开始写数据,如果掉电发生在这一点上,那么user看到一个10Mib大小的文件,在文件后部是有个hole。注意,即便I/O不是同步的,UBIFS在开始写数据 meta data到flash之前就返回。Write back将在某个时刻开始写flash media, 如果在write back过程发生掉电,那么同样会产生hole。因此,UBIFS并不能像JFFS2那样,很完美的保留掉电前

24、写下的数据以及文件尺寸,主流文件系统比如ext3也没有提供JFFS2类似的功能。虽然,有时人们用UBIFS替代JFFS2,人们希望UBIFS能够像JFFS2一样行事,这是可行的,需要hack一下UBIFS代码。之所以UBIFS还没有这样实现,是因为这个需求并没有那么强烈。UBIFS作为一个异步的文件系统,应用程序应该在需要的时候同步他们的文件,这同样适用于大部分linux 文件系统,然而,一些应用忽略了这一点,没能够正确的同步文件。UBIFS快速压缩支持UBIFS支持快速的压缩,UBIFS在把数据写入flash 存储介质之前压缩数据,在读出来时解压数据,这个压缩/解压缩过程对与用户来说是完全透

25、明的。UBIFS仅仅压缩文件数据,而目录,设备节点等是不压缩的。Meta data和indexing信息也是不压缩的。当前UBIFS支持LZO和zlib压缩器。ZLib提供了更好的压缩率,但是LZO在压缩和解压时的速度更快。LZO是UBIFS和mkfs.ubifs的缺省压缩处理器,当然你可以在mkfs.ubifs命令选项中使用-x来disable UBIFS压缩。UBIFS把数据分割为4KiB的块然后对每一个chunks进行单独压缩。这不是最优的,因为大块的数据压缩效果更好,即便如此仍然提供了客观的flash空间效益。比如,一个真实的root file system镜像利用LZO压缩器可以减小

26、40%空间,而用zlib压缩器则减少50%空间。这意味如果你可以把一个300MB的文件系统放到256MiB的UBI volume中,而且任然有100MiB的空闲空间。然而这可能随着文件系统存放的内容不同而不同,比如,如果你的文件系统保存的都是mp3文件,UBIFS无法有效的压缩他们,因为mp3文件本身就是被压缩的。在UBIFS中是可以针对每个文件节点来disable/enable压缩功能的,方法是设置或者清除inode节点的compression标志。注意,这个压缩标志对于目录是可继承的,也就是说这个目录下的文件和子文件在创建时,他们的压缩标志是继承自父目录的。还要注意的是JFFS2 LZO压

27、缩和UBIFS的zlib压缩有轻微不同,UBIFS使用crypto-API缩小方法,而JFFS2直接使用zlib库。导致UBIFS和JFFS2使用不同的zlib压缩选项。名义上,JFFS2使用缩小level3,window bits15,而UBIFS使用level6 windows bit -11(负号使得zlib避免放一个header到数据流中)。经验显示JFFS2压缩率稍微小一些,解压速度慢一些,但是压缩速度要快一些。UBIFS CRC校验操作UBIFS写入到介质的每一片数据都有一个CRC32 checksum,UBIFS使用CRC来保护data和meta data。每次读meta dat

28、a时,CRC校验码都会被验证。CRC-32校验是非常强大的,几乎所有的数据损坏都可以检查到。UBI也是如此,验证每一片meta data。data CRC在缺省情况下是不验证的,这能改善文件系统的读速度,当然UBIFS可以在mount时用chk_data_crc,来切换为data验证。这会减少UBIFS的读速度,但是提供了更好的数据完成性保护。使用这个选项,UBIFS读取的每一片信息都会被验证,任何数据损坏也都会被检查到。注意,当前UBIFS不能disable CRC-32的写计算,因为UBIFS在recovery过程依赖于它,当从一个unclean reboot恢复,replay日志时,UB

29、IFS需要检测broken和写了一半的UBIFS nodes然后抛弃他们,在这里UBIFS依赖于CRC-32 checksum。换句话来说,如果你使用UBIFS时disable掉CRC-32,但是你仍然为每一片数据生成了CRC-32 checksum, 你可以随时激活读校验注意:在2.6.39之前default UBIFS行为是相反的, UBIFS缺省支持CRC-32, 使用no_chk_data_crc来disable它。UBIFS的Read aheadRead ahead是一个文件系统的优化技术,每次读取的数据比用户请求的数据多一些。这个主意是基于文件的访问一般都是从开始向后顺序进行的,所

30、以文件系统试着把将来可能用到的数据提前读出了。LINUX VFS本身会做这个read ahead而不需要file system的支持。这对于传统的块设备文件系统工作良好,但是UBIFS不会得益于此。UBIFS工作于UBI API之上,而UBI工作与MTD API之上,MTD API是同步地, MTD API是非常简单的,没有任何请求队列。这意味这VFS 阻塞住 UBIFS readers, 让他们等待read ahead过程。Block device API是异步的 readers不需要等待read ahead,VFS read ahead是为hard drives设计的。但是raw flas

31、h设备和hard drive是非常不同的,raw flash设备不需要耗时的寻道时间,所以适合hard disk的技术并不适合flash设备。也就是说,VFS的read ahead仅仅会使得UBIFS变慢,所以UBIFS 会disable 掉VFS的read ahead。但是UBIFS有他自己内部的read ahead,我们称之为bulk read。你可以在mount时增加bulk_read选项来使能bulk read功能。有些flash可能一次读出全部数据要比分多次读出数据要快。例如,OneNAND可以做read-while-load如果它读取超过一个NAND page。所以UBIFS可以通

32、过一次读取较大的data chunks来获取性能上的提升,这就是bulk read 要做的如果UBIFS注意到一个文件正在被顺序的读取,UBIFS看到接下来的数据就存放在相同的eraseblock中,则UBIFS开始read ahead数据,通过使用大的read request。UBIFS把这些提前读取的数据放到文件的cache中,所以用户的进一步读取可以直接从cache中获得。很明显,bulk read 在某些情况下,可能会减慢UBIFS。此外注意在高度碎片化的文件系统上,bulk read并不适合,尽管UBIFS不会主动碎片文件系统,但是也不会de-fragment文件系统。比如数序的写一

33、个文件,那么不会有变得碎片化。但是如果你同时写多个文件,他们就可能变得碎片化(这也依赖于write back怎么样提交更新),UBIFS是不会自动deframent他们。当然,可以实现一个background的defragmenter。我们也可以使用per inode的日志头来避免在一个LEB上混合属于不同的inode的数据节点,所以仍然有改善的余地。UBIFS超级用户空间UBIFS向超级用户保留了一些空间,这意味着当文件系统对于普通用户为满时,仍然有一点保留空间给 super user。其他文件系统比如ext2也有类似的特点,mkfs.ubifs有一个-R选项可以用来标识保留空间的尺寸。缺省

34、情况下仅仅root用户可以使用保留空间,但是可以扩展特权用户的列表。UBIFS可以记录几个user和group IDs在超级块中,允许他们利用保留空间。尽管 mkfs.ubifs工具没有相应的命令行选项,但是很容易实现这个功能。注意,UBIFS在mount文件系统时会输出保留空间的数目。UBIFS支持的Mount特定选项下面是UBIFS-specifi特定的mount选项 1. chk_data-crc2. no_chk_data-crc3. bulk_read4. no_bulk_read此外UBIFS支持标准的sync mount 选项,可以用来disable UBIFS write ba

35、ck和write buffer,使得写过程完全同步。注意UBIFS不支持atime,所有atime mount选项不起任何作用。UBIFS对于空闲空间处理的缺陷传统的文件系统,比如ext2可以很容易的计算出空闲空间,计算是非常精确的,用户对此已经习以为常。然后,UBIFS则完全不同了,UBIFS无法汇报它还有多少空闲空间可用,只能汇报最少的可用空间数,这个数目通常会少于实际的数目,有时差错甚至很大。UBIFS汇报的空闲空间的数目少于实际拥有的,是基于以下几个理由:第一因素是UBIFS的快速压缩。用户一般认为文件系统汇报了N bytes空闲空间,那么就意味着可以写入N bytes的文件数据。因为

36、压缩的存在,这种想法就不成立了,根据数据压缩程度的不同,UBIFS可以写入的数据可能数倍于汇报的空闲空间 。当UBIFS计算空闲空间时,他并不知道即将写入的数据的特性,因此无法考虑压缩,所以就假定为最坏的情况,数据没有压缩。虽然这看起来问题不大,但是综合考虑压缩和write back,压缩就变成了估算空闲空间的大问题。换句话说,UBIFS无法知道cached dirty数据的压缩,想知道结果的唯一办法就是执行压缩。第二因素是回写操作。假定在page cache中有X bytes的脏数据,他们将在某个时间被刷入flash 存储介质。UBIFS当前需要X+O bytes空间来写这些数据,O是文件系

37、统开支(比如数据的index,以及每个data node需要一个header) 问题是UBIFS无法精确的计算出X和O,它使用悲观的最坏情况的计算,所以当cached data被刷入flash, 所需的flash空间可能原少于需要的X+O,例如看下面的情况:$ dfFilesystem 1K-blocks Used Available Use% Mounted onubi0:ubifs 49568 49568 0 100% /mnt/ubifs$ sync$ dfFilesystem 1K-blocks Used Available Use% Mounted onubi0:ubifs 4956

38、8 39164 7428 85% /mnt/ubifs第一次df汇报zero空闲空间,但是sync后汇报了15%的空闲空间,这是因为有很多cached的dirty data,UBIFS为他们保留了所有的空闲空间,但是在flash media过程中,仅使用了部分flash space。下面是UBIFS为什么保留这个多空闲空间的理由1.还是关于compression。数据以uncompressed形式存储在缓存中,UBIFS并不能预估这些数据的压缩,所以它假定数据完全不能压缩。然而,现实生活数据是很容易压缩的,除非.tgz或者.mp3文件,这就导致了对X的过分估计。2.归咎于设计,UBIFS no

39、des不会跨越earseblock的边界,所以在每个擦除块的末尾处都会有一些小的浪费空间,这个浪费的flash空间依赖于数据写入和更改的顺序,传统的UBIFS会悲观的估计这个浪费空间为最大值,这也导致了对O的过份估计。因此UBIFS在同步后可以更精确的估计空闲空间值像上面提到的,UBIFS不会跨越LEB边界。考虑下面数字: 1.UBIFS node最大尺寸是4256字节2.UBIFS node最小尺寸是56 字节3.依赖于名字长度,目录项节点占据56304字节4.LEB尺寸:典型的NAND flash 128KiB的物理擦除块2048字节的NAND page,LEB的尺寸是126KiB(或者1

40、24KiB如果NAND chip不支持sub-pages)。因此如果大部分flash上的节点是非压缩的data nodes, UBIFS将会浪费126KiB LEB的最后1344bytes。但是现实生活中的数据通常是压缩的,所以node尺寸可能发生变化,因此在删除块末尾的wasted space范围为04255。UBIFS把一些小的节点,比如目录项节点放到LEBs末尾来减少wasted space,但是不理想,UBIFS仍然在LEB的末尾浪费掉大块的空间。当汇报空闲空间时,UBIFS不知道哪种数据,以何种顺序写入flash media。因此,它评估每个LEB的wastage为最大可能值4255

41、这个计算对大多数现实世界都是太悲观了,真实的浪费要远少于4255。然而,UBIFS汇报给用户空间程序的是绝对最小值。以上意味着LEB越大,UBIFS对空闲空间的预测越准确,比如128KiB擦除块要好于16KiB的参数块。Dirty space是曾经被UBIFS nodes使用过的空间,但是由于改变或者转移导致这个空间变得无效。例如,如果文件的内容被re-write,那么相应的数据节点变成无效,当新的数据data写入flash media,无效的节点包含 dirty space,当然还有其他的机制会导致dirty space出现。 UBIFS无法直接重用dirty space,因为相应的fla

42、sh areas没有包含所有的0xff bytes。在dirty space可以重用前,UBIFS不得不垃圾收集相应的LEBs,垃圾收集回收dirty space的方法和JFFS2是相同的。粗略的讲,UBIFS垃圾收集选取一个LEB,这个LEB包含一些dirty space,然后把这个LEB上的有效UBIFS节点移到GC reserverd LEB上。这将消耗GC reserved LEB的一些空闲空间,GC选取另外一个需要收集的LEB,然后把有效数据移到这个GC reserved LEB,持续这个过程直到LEB变满。GC选取另外一个 reserved LEB,继续这个过程。UBIFS有一个概

43、念叫最小I/O 单位, 描述可以写入flash数据的最小数目,一般情况下UBIFS工作在large-page NAND flash上,最小I/O单位是2KiB。事实上,UBIFS GC虽然尝试不浪费任何空间,但是有时并不能如愿,UBIFS不一定能够回收那些dirty空间小于I/O unit的dirty space。当UBIFS向users汇报空闲空间时,对待dirty space为可用空间,因为GC可能会回收这部分空间为空闲空间,但如上面分析的,UBIFS无法回收所有的dirty space为空闲空间,更坏的情况是UBIFS无法确切知道它可以回收多少dirty space,再一次UBIFS使用

44、最悲观的计算。因此dirty space越少,UBIFS汇报的free space越准确。在实际应用中,这意味着一个满的文件系统要比一个空的文件系统更难预测空闲空间,因为满的文件系统有太多的dirty space。注意,解决这个问题,UBIFS可以在statfs()中运行GC, GC将把dirty space变为free space, 因此预测空闲空间就变得更精确。然而,这将导致statfs变得非常的慢,因此调用statfs的应用的行为将不可预测。此外也可以使用JFFS2使用的background GC。可能已经知道,UBIFS在flash media上维护文件系统的index。index占据

45、flash的一部分空间。UBIFS journal保存着FS data。journal中的FS data没有index, 这意味着on flash index没有指向他们。 journal FS data的index是建立在RAM中的,当文件系统被mount时,UBIFS要扫描整个journal区,然后在RAM中重建index。日志在某种程度像是UBIFS中的一个JFFS2文件系统。 journal data在提交时会变成indexed,在UBIFS提交时,更新on flash index,使得index指向journal data,然后UBIFS挑选其他的LEBs作为新的journal, 所

46、以journal在提交后会改变位置,这就是UBIFS的journal特点,日志区不是固定的。UBIFS精确的记录着index size。也就是,UBIFS一直很清楚当前on flash index占据了多少空间。然而UBIFS无法精确的预测在提交后on flash index要增加或减少多少,再一次的,UBIFS考虑最坏的情况。当然在提交后UBIFS再次知道index的确切尺寸。sync()不仅仅flush左右的脏数据,而且也会提交journal。这意味者同步过的文件系统对空闲空间的预测更准确。事实上,UBIFS本可以精确的预计index size而无须commit操作,但是UBIFS作者并没

47、有实现它,因为实现很困难,而index size的影响又很小。Raw flash vs FTL devicesFTL 全称 Flash Translation Layer, 是一个软件层用来在Flash存储设备上模拟一个block device。所有的FTL设别都提供了一个block I/O访问接口,虽然这些接口有不同的规范定义的,比如MMC, eMMC, SD, USB mass storage, ATA,但是他们都提供了对块设备的访问。基于块设备的访问意味着整个设备可以看作是一个线性blocks的排列,每一个块都可读可写。尽管大部分常用flash hardware有FTL, 但是仍让存在一

48、些裸flash没有FTL,比如各种手持设备和嵌入式系统。Raw flash设备和block设备是非常不同的,他们之间的工作模式不同,raw flash和block设备相比,有更多的限制和问题需要软件考虑这些问题。使用FTL层,这些限制和问题都可以被FTL屏蔽。UBIFS文件系统被设计用来使用raw flash,换句话说,它认为设备有很多eraseblocks,可以写入,读出,或者擦除,UBIFS负责考虑以out-of-place方式写数据,做垃圾收集等等。UBIFS利用UBI来实现磨损平衡和坏块管理,正常的block drive都不需要处理这些事情。使用raw flash的好处是,你知道你正在做什么,UBI/UBIFS处理NAND flash的所有事情,包括bad erase-blocks和wear-leveling。它保证掉电处理。同时它是开放的,你可以验证,测试,修改它。没有隐藏它能做什么不能做什么。理论上,UBIFS可以更好的工作因为他比FTL知道更多的信息,例如,UBIFS知道删除的文件,而FTL不知道,所以FTL可能为已经删除的文件保留sectors。无论如何,raw flashed在嵌入式世界中广泛使用,这也是为什么开发UBIFS的原因。UBIFS文件系统的移植配置mtd支持UBI接口Device D

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 管理/人力资源 > 物业管理

一课资料网交流QQ群:678591818  网站客服QQ:2935355895 copyright@ 2020-2024 www.ekdoc.com网站版权所有

经营许可证编号:鄂ICP备20004875号