UBIFS

3个子系统:

  • MTD 子系统: 提供访问flash 芯片的统一接口。MTD提出了MTD设备的概念(/dev/mtd0),MTD设备就是raw flash。
  • UBI 子系统: 在MTD子系统之上。坏块管理,均衡负载处理,和volume管理。
  • UBIFS 文件系统: 在UBI volumes之上

ubi工具:

  • mkfs.uibfs: 生成镜像
  • ubiupdatevol: 写ubi volumes
  • ubinize:在raw flash上创建image

jffs2:

  • 最初是为了32M的Nor Flash设计的,suoyi扩张没有ubi的扩展性好
  • jffs2在‘file system level’层面存在问题,而ubi只会在"raw flash level"的层面出现问题。

ubi的很多基础构想都是和jffs2是一样的,可以读jffs2的设计文档:http://sources.redhat.com/jffs2/jffs2.pdf

FTL设备:

raw flash(MTD设备)和emmc:


  • 我们一般所说的nand flash是指raw nand flash。flash 本身没有坏块管理。
  • raw flash的统一性做的不够好,各个厂家都有自己的特性,给使用者带来了很多麻烦,emmc nand屏蔽了这种差异,统一了标准,使用起来相对容易。
  • 在linux 系统中,raw nand属于mtd设备,可在/proc/mtd下查看。MTD驱动是用来访问raw flash芯片的,不能用来访问emmc flash。

Raw Flash和FTL

FTL: Flash Translation Layer,在flash硬件上模拟一个block device。现在很多的FTL都是以firmware的形式烧写在存储设备里里的。

所有的FTL设备都提供访问I/O的接口,这些接口会根据不同的设备会不一样,如MMC,eMMc,sd,USB mass storage,ATA这间的I/O接口会不一样,但是他们都提供最基本的block-based access。

linux有一个block device的抽象。例如hard drives硬盘是块设备。linux有很多的文件系统和block I/O子系统。所以抽象后,目的是为了同样的软件可以工作在不同的FTL设备上。

现在很多的厂商的存储设备都有FTL,但是也有的是bare flash(无FTL)。 Raw flash devices 和block devices有很大的不同,他们有不同的工作模式。和block设备相比,raw flash有更加严格的约束,当然也有更多的问题。

UBIFS文件系统是为了raw flash而设计的。所以UBIFS不能作用于block device,因为UBIFS是raw flash device模型。UBIFS它假定设备有eraseblocks,也就是该设备可以read, write,erase。UBIFS关心是否把数据write到了正确位置、处理垃圾回收等等,UBIFS使用UBI的wear-leveling 和坏擦除块处理,所有这些功能,通常block device都不需要。

有的人会问: “为什么用raw flash而不直接使用eMMC,或者类似eMMC的设备呢?”这需要根据系统的需求而定。

  • Bare Nand芯片便宜并且简单,对于小的系统来说是很重要的。size大小相同的容量,FTL比raw flash复杂的多,因为FTL设备内部有额外的控制器。但是各个厂商趋向于用FAT device,并且在大量的销售,FAT device的价格也逐渐的在下降。
  • 如果你想用一个FAT 文件系统,大部分情况下,你应该坚持使用FTL device(eMMC, MMC, SD, whatever)。
  • 必须用FTL设备作为系统的存储(rootfs),并且使用比较健壮的文件系统如ext3。在这种情况下,你需要考虑断电容忍度。
  • FTL device是一个‘黑盒子’。
  • 我们在新闻里听过这样的报道,如果突然断电,MMC, eMMC和SD卡坏掉了或者数据丢失,这说明了一件事情:就是那些厂商的FTL固件没处理好。再次强调,并不是所有的MMC/eMMC/SD卡都会出现问题,不同的厂商不一样,所以需要小心选择这些产品。
  • 回顾历史,你会发现很多FTL device都是用的FAT文件系统来存储照片和视频的。 FAT文件系统并不是一个可靠的文件系统,也就是说有些FTL设备可能不是非常可靠。事实上,丢几张照片并不是什么大问题,然而,确保系统库不会因为断电而损坏才是是至关重要的。
  • 好的FTL肯定是一个相当复杂的软件,特别是处理MLC Nand的时候(MLC Nand的擦除块生命周期很短,但是应用在很多现代存储设备中)。在固件中实现FTL可能是一项困难的任务,运行它可能需要一个强大的控制器,即便如此,我们还是需要对厂商的伎俩和妥协去保持‘good enough’和便宜保持怀疑的态度。 有些厂商针对FAT文件系统对FTL进行了优化,如果你在此之上用ext3,可能会有意想不到的问题,这些问题很难定位,因为厂商的FTL是闭源的。
  • FTL设备变得越来越好且越来越流行,虽然我们很难判断一个FTL的好坏(尽管厂商吹嘘他们的产品非常完美)。通常情况下,使用FTL设备并没什么错,只要你相信它,或者你已经测试过它,或者它符合你系统需求。
  • 在使用raw flash的时候,我们能明确的知道它在做什么,没有黑匣子。 UBI/UBIFS处理了所有的关于NAND flash的东西,比如坏块处理、损耗均衡、它能容忍突然断电;UBI/UBIFS是开源的,你可以知道它干了什么,它不会说谎,你可以测试它并且fix。 但是厂商的FTL device不一样,它是闭源的。
  • 理论上,UBIFS应该做的更好,因为在文件方面,UBIFS比FTL知道的更多更全面。 比如,UBIFS知道已删除的文件,但是FTL不知道,所以FTL可能需要做很多不必要的工作来维护sectors上已删除的文件。有些FTL设备可能做了一些优化,但是通常,相同的Nand 芯片,一般UBIFS(运行在相同芯片的Bare Nand上)比传统的FS(在FTL device上)做得更好。另一方面,FTL device可能包含了多个Nand 芯片,并行运行,提供了快速的I/O,SSD可能就是一个很好的例子。
  • 显然的,FTL device的优势在于你在上面运行比较可靠的固件。 UBIFS的作者曾经在一个好品牌的eMMC上进行断电测试,发现一些很严重问题。此外,有人测试发现ext3在eMMC上是不可用的:断电的时候发现eMMC的sector不可读,读的时候返回ECC错误,对于ext3来说读错误是致命的问题,因为ext3不是为了处理读错误而设计的。 fsck.ext3工具也不能修复坏的不可读的sectors。
  • 尽管如此,个人还是偏向使用raw flash而不是FTL device,主要是在嵌入式世界中,这就是开发UBIFS的原因。
  • U盘,MMC, SD等移动设备,通常我们都称之为flash,但是他们都不是MTD设备。他们超出了MTD子系统的范畴。
  • 为了在在MTD设备上方便的使用文件系统,需要一个软件来模拟block设备,这个软件层叫FTL(Flash Translation Layer)。

MTD设备到底是block设备or 字符设备呢?

  • 字符设备:例如键盘,鼠标,你从中读取到当前的数据。这些设备没有size,不能seed-ed定位。
  • 块设备:有固定的size,可以被seek-ed定位。一个block一般有多个字节,通常是512字节。
    Flash与block和character设备的描述都不相符,只是flash的行为和block设备相似,但是又有不同。比如block设备不能区分write和erase的操作。 因此,为了匹配flash的特性,一个特殊的设备类型:MTD产生了。
  • 所以,MTD既不是block也不是字符设备。

MTD和mtdblock设备

mount命令的需求,你只能挂载块设备(有文件系统),而不能对字符设备进行挂载

  • mtd-utils工具只能应用与/dev/mtdN的MTD字符设备
  • mount、umount命令只对/dev/mtdblockN的MTD块设备有效
  • /dev/mtdN和/dev/mtdblockN是同一个MTD设备的同一个分区(N一样)

block设备的缺点:

  • 最小单位的写是一整个块,所以即使写1byte的数据, 它的操作也是一整块的, 先读取一整块数据到内存备份,擦除一整块数据,然后写入,这样很容把原来的数据给丢失(比如还没写完一整块就断电了)。 保证块存储设备的安全和完整性是很难的,但是有了UBIFS文件系统,是可以解决这些问题的的。

MTD

MTD为raw flash设备提供了一个抽象层,这样可以用同样的api操作不同的flash设备,如Nand,OneNand,Nor,Ecc’d Nor等等。

MTD不能在MMC,eMMC,SD,U盘上工作,因为这些设备都不是raw flash,这些设备中都有一个FTL(Flash Translation Layer)的固件,这个FTL让这些设备变得像like block device。

MTD子系统有下面一些借口:

  • MTD字符设备-通常是/dev/mtd0, /dev/mtd1等。这些字符设备可以访问raw flash的I/O。支持许多ioctl来操作/dev/mtdN设备,如擦除,标记坏块,检测坏块,获取MTD设备信息等。
  • sysfs接口:比ioctl和/proc/mtd借口要新,可以在内核文档:Documentation/ABI/testing/sysfs-class-mtd中找到。
  • /proc/mtd提供了MTD设备的信息,这是老的接口了,可以被sysfs接口代替,sysfs可以提供更多info。

MTD API

api在include/linux/mtd/mtd.h,MTD api的函数和数据结构被高层的内核代码所使用,如flash file systems要控制mtd设备、也有驱动工程师将他们自己的raw flash加入到MTD子系统中。在struct mtd_info中定义了很多的methods,这些methods需要相应的驱动程序去访问设备。

kernel-3.4之前:直接调用 一个指向struct mtd_info指针 的成员方法。
kernel-3.4之后:这些方法在mtd子系统的core code中已经实现了
如何使用MTD api可以看drivers/mtd/tests的测试程序。

mtdblock驱动

MTD中可用的mtdblock驱动程序是一个古老的工具,它在MTD设备之上模拟块设备, mtdblock甚至都没有坏块处理,所以mtdblock是不可靠的Nand flash设备。即使修改一个字节,mtdblock driver会缓存整个erase block在RAM中,然后擦除整个block,然后把修改,最后把缓存在内存中整块数据写回设备。目前mtdblock驱动没有做wear-leveling和bits-flips的处理。

通常人们认为mtdblock是通用的FTL层,并尝试在bare flash之上使用mtdblock,然后在mtdblock上使用基于块的文件系统。 在很多场景中这样是错误的,换而言之,除非你知道你自己在做什么。

mtdblock也有只读的驱动,在uCLinux上有使用。

Instead of using mtdblock old driver,你可以试试UBI提供的R/O block device emulation。详情参考(R/O block devices on top of UBI volumes):http://www.linux-mtd.infradead.org/doc/ubi.html#L_ubiblock