Linux 中的 Flash 文件系统

作者: 华清远见嵌入式培训中心

嵌入式系统与通用 PC 机不同,一般没有硬盘这样的存储设备而是使用 Flash 闪存芯片、小型闪存卡等专为嵌入式系统设计的存储装置,本文分析了嵌入式系统中常用的存储设备及其管理机制,介绍了常用的基于 FLASH 的文件系统类型。

1.嵌入式系统存储设备及其管理机制分析

构建适用于嵌入式系统的 Linux 文件系统,必然会涉及到两个关键点,一是文件系统类型的选择,它关系到文件系统的读写性能、尺寸大小; 另一个就是根文件系统内容的选择,它关系到根文件系统所能提供的功能及尺寸大小。

嵌 入式设备中使用的存储器是像 Flash 闪存芯片、小型闪存卡等专为嵌入式系统设计的存储装置。Flash 是目前嵌入式 系统中广泛采用的主流存储器,它的 主要特点是按整体 / 扇区擦除和按字节编程,具有低功耗、高密度、小体积等优点。目前,Flash 分为 NOR, NAND 两种类型。

NOR 型闪存可以直接读取芯片内储存的数据,因而速度比较快,但是价格较高。NOR 型芯 片,地址线与数据线分开,所以 NOR 型芯片可以像 SRAM 一样连在 数据线上,对 NOR 芯片可以“字”为基本单位操作,因此传输效率很高,应用程序可以直接在 Flash 内运行,不必再把代码读到系统 RAM 中运行。它与 SRAM 的最大不同在于写操作需要经过擦除和写入两个过程。

NAND 型闪存芯片共用地址线与数据线,内部数据 以块为单位进行存储,直接将 NAND 芯片做启动芯片比较难。NAND 闪 存是连续存储介质,适合放大文件。 擦除 NOR 器件时是以 64-128KB 的块进行的,执行一个写入 / 擦除操作的时间为 5s;擦除 NAND 器件是以 8-32KB 的块进行的,执行相同的操作最 多只需要 4ms。NAND Rash 的单元尺寸几乎是 NOR 器件的一半,由于生产过程更为简单,NAND 结构可以在给定的模具尺寸内提供更高的容量,也就相应地降低了价格。NOR flash 占据了容量为 1―16MB 闪存市场的大部分,而 NAND flash 只是用在 8―128MB 的产品当中,这也说明 NOR 主要应用在代码存储介质中,NAND 适合于数据存储。寿命 (耐用性),在 NAND 闪存中每个 块的最大擦写次数是一百万次,而 NOR 的擦写次数是十万次。NAND 存储器除了具有 10 比 1 的块擦除周期优势,典型的 NAND 块尺寸要比 NOR 器件小 8 倍,每个 NAND 存储器块在给定的时间内的删除次数要少一些。

所有嵌入式系统的启动都至少需要使用某种形式的永久性存储设备,它们需要合适的驱动程序,当前在嵌入式 Linux 中有三种常用的块驱动程序可以选择。

  • Blkmem 驱动层

Blkmem 驱动是为 uclinux 专门设计的,也是最早的一种块驱动程序之一,现在仍然有很多嵌入式 Linux 操作系 统选用它作为块驱动程,尤其是在 uClinux 中。它相对来说是最简单的,而且只支持建立在 NOR 型 Flash 和 RAM 中的根文件系统。使用 Blkmem 驱动,建立 Flash 分区配置比 较困难,这种驱动程序为 Flash 提供了一些基本擦除 / 写操作。

  • RAMdisk 驱动层

RAMdisk 驱动层通常应用在标准 Linux 中无盘工作站的启动,对 Flash 存储器并不提供任何的直接支持, RAM disk 就是在开机时,把一部分的内存虚拟成块设备,并且把之前所准备好的档案系统映像解压缩到该 RAM disk 环境中。当在 Flash 中放置一个压缩的文件系统,可以将文件系统解压到 RAM,使用 RAM disk 驱动层支持一个保持在 RAM 中的文件系统。

  • MTD 驱动层

为 了尽可能避免针对不同的技术使用不同的工具,以及为不同的的技术提供共同的能力,Linux 内核纳入了 MTD 子系统 (memory Technology Device)。它提供了一致且统一的接口,让底层的 MTD 芯片驱动程序无缝地与较高层接口组合在一起。JFFS2, Cramfs, YAFFS 等文件系统都可以被安装成 MTD 块设备。MTD 驱动也可以为那些支持 CFI 接口的 NOR 型 Flash 提供支持。虽然 MTD 可以建立在 RAM 上, 但它是专为基于 Flash 的设备而设计的。MTD 包含特定 Flash 芯片的驱动程序,开发者要选择适合自己系统的 Flash 芯片驱动。Flash 芯片驱动 向上层提供读、写、擦除等基本的操作,MTD 对这些操作进行封装后向用户层提供 MTD char 和 MTD block 类型的设备。MTD char 类型的设备包括 /dev/mtd0, /dev/mtdl 等,它们提供对 Flash 原始字符的访问。MTD block 类型的设备包括 /dev/mtdblock0,/dev/mtdblock1 等,MTD block 设备是将 Flash 模拟成块设备,这样可以在这些模拟的块设备上创建像 Cramfs, JFFS2 等格式的文件系统。

MTD 驱动层也支持在一块 Flash 上建立多个 Flash 分区,每一个分区作为了一个 MTD block 设备,可以把系统软件和数据等分配到不同的分区上,同时可以在不同的分区采用不用的文件系统格式。这一点非常重要,正是由于这一点才为嵌入式系 统多文件系统的建立提供了灵活性。

2. 基于 Flash 的文件系统

鉴 于 Flash 存储介质的读写特点,传统的 Linux 文件系统己经不适合应用在嵌入式系统中,像 Ext2fs 文件系统是 为像 IDE 那样的块设备设计的,这 些设备的逻辑块是 512 字节、1024 字节等大小,没有提供很好的扇区擦写支持,不支持损耗平衡,没有掉电保护,也没有特别完美的扇区管理,这不太适合于 扇区大小因设备类型而划分的闪存设备。基于这样的原因,产生了很多专为 Flash 设备而设计的文件系统,常见的专用于闪存设备的文件系统如下:

  • Romfs

传 统型的 Romfs 文件系统是最常使用的一种文件系统,它是一种简单的、紧凑的、只读的文件系统,不支持动态擦写保存; 它按顺序存放所有的文件数据,所以 这种文件系统格式支持应用程序以 XIP 方式运行,在系统运行时,可以获得可观的 RAM 节省空间。uClinux 系统通常采用 Romfs 文件系统。

  • Cramfs

Cramfs 是 Linux 的创始人 Linus Torvalds 开发的一种可压缩只读文件系统在 Cramfs 文件系统中,每一页被单独压缩,可以随机页访问,其压缩比高达 2:1, 为嵌入式系统节省大量 的 Flash 存储空间。Cramfs 文件系统以压缩方式存储,在运行时解压缩,所以不支持应用程序以 XIP 方式运行,所有的应用程序要求被拷到 RAM 里去 运行,但这并不代表比 Ramfs 需求的 RAM 空间要大一点,因为 Cramfs 是采用分页压缩的方式存放档案,在读取档案时,不会一下子就耗用过多的内存空间,只针对目前实际读取的部分分配内存,尚没 有读取的部分不分配内存空间,当我们读取的档案不在内存时, Cramfs 文件系统自动计算压缩后的资料所存的位置,再即时解压缩到 RAM 中。另外,它的速度快,效率高,其只读的特点有利于保护文件系统免受破坏,提 高了系统的可靠性; 但是它的只读属性同时又是它的一大缺陷,使得用户无法对其内容对进扩充。Cramfs 映像通常是放在 Flash 中,但是也能放在别的文 件系统里,使用 loopback 设备可以把它安装别的文件系统里。使用 mkcramfs 工具可以创建 Cramfs 映像。

  • Ramfs/Tmpfs

Ramfs 也是 Linus Torvalds 开发的,Ramfs 文件系统把所有的文件都放在 RAM 里运行,通常是 Flash 系统用来存储一些临时性或经常要修改的数据,相对于 ramdisk 来说,Ramfs 的大小可以随着所含文件内容大小变化,不像 ramdisk 的大小是固定的。Tmpfs 是基于内存的文件系统,因为 tmpfs 驻留在 RAM 中,所以写 / 读操作发生在 RAM 中。tmpfs 文件系统大小可随所含文件内容大小变化,使得能够最理想地使用内存;tmpfs 驻留在 RAM,所以读和写几乎都是瞬时的。tmpfs 的一个 缺点是当系统重新引导时会丢失所有数据。

  • JFFS2

JFFS2 是 RedHat 公司基于 JFFS 开发的闪存文件系统,最初是针对 RedHat 公司的嵌入式产品 eCos 开发的 嵌入式文件系统,所以 JFFS2 也 可以用在 Linux,uCLinux 中。JFFS 文件系统最早是由瑞典 Axis Communications 公司基于 Linux2.0 的内核为嵌入式系统开发的文件系统。JFFS2 是一个可读写的、压缩的、日志型文件系统,并提供了 崩溃 / 掉电安全保护,克服了 JFFS 的一些缺点: 使用了基于哈希表的日志节点结构,大大加快了对节点的操作速度; 支持数据压缩;提供了“写平衡”支持; 支 持多种节点类型;提高了对闪存的利用率,降低了内存的消耗。这些特点使 JFFS2 文件系统成为目前 Flash 设备上最流行的文件系统格式,它的缺点就是当 文件系统已满或接近满时,JFFS2 运行会变慢,这主要是因为碎片收集的问题。

  • YAFFS

YAFFS/YAFFS2 是一种和 JFFSx 类似的闪存文件系统,它是专为嵌入式系统使用 NAND 型闪存而设计的一种日 志型文件系统。和 JFFS2 相比它 减少了一些功能,所以速度更快,而且对内存的占用比较小。此外,YAFFS 自带 NAND 芯片的驱动,并且为嵌入式系统提供了直接访问文件系统的 API,用 户可以不使用 Linux 中的 MTD 与 VFS,直接对文件系统操作。YAFFS2 支持大页面的 NAND 设备,并且对大页面的 NAND 设备做了优化。 JFFS2 在 NAND 闪存上表现并不稳定,更适合于 NOR 闪存,所以相对大容量的 NAND 闪存,YAFFS 是更好的选择。

具体的嵌入式系统设计中可根据不同目录存放的内容不同以及存放的文件属性,确定使用何种文件系统。

  • UBIFS

诺基亚开发的新文件系统,意在取代 JFFS2.