Ext2fs 是 Linux 事实上的标准文件系统,它已经取代了它的前任 — 扩展文件系统
(或 Extfs)。Extfs 支持的文件大小最大为 2 GB,支持的最大文件名称大小为 255 个字
符 — 而且它不支持索引节点(包括数据修改时间标记)。Ext2fs 做得更好,它的优点是:
(1) Ext2fs 支持达 4 TB 的内存。
(2) Ext2fs 文件名称最长可以到 1012 个字符。
(3) 当创建文件系统时,管理员可以选择逻辑块的大小(通常大小可选择 1024、2048
和 4096 字节)。
(4) Ext2fs 了实现快速符号链接:不需要为此目的而分配数据块,并且将目标名称
直
接存储在索引节点(inode)表中。这使性能有所提高,特别是在速度上。
因为 Ext2 文件系统的稳定性、可靠性和健壮性,所以几乎在所有基于 Linux 的系统
(包括台式机、服务器和工作站 — 并且甚至一些嵌入式设备)上都使用 Ext2 文件系统。
然而,当在嵌入式设备中使用 Ext2fs 时,它有一些缺点:
(1) Ext2fs 是为象 IDE 设备那样的块设备设计的,这些设备的逻辑块大小是 512 字
节,1 K 字节等这样的倍数。这不太适合于扇区大小因设备不同而不同的闪存设备。
(2) Ext2 文件系统没有提供对基于扇区的擦除/写操作的良好管理。在 Ext2fs 中,
为了在一个扇区中擦除单个字节,必须将整个扇区复制到 RAM,然后擦除,然后重
写入。考虑到闪存设备具有有限的擦除寿命(大约能进行 100,000 次擦除),在此
之后就不能使用它们,所以这不是一个特别好的方法。
(3) 在出现电源故障时,Ext2fs 不是防崩溃的。
Ext2 文件系统不支持损耗平衡,因此缩短了扇区/闪存的寿命。(损耗平衡确保将
地址范围的不同区域轮流用于写和/或擦除操作以延长闪存设备的寿命。)
Ext2fs 没有特别完美的扇区管理,这使设计块驱动程序十分困难。
由于这些原因,通常相对于 Ext2fs,在嵌入式环境中使用 MTD/JFFS2 组合是更好的
选择。
用 Ramdisk 挂装 Ext2fs:
通过使用 Ramdisk 的概念,可以在嵌入式设备中创建并挂装 Ext2 文件系统(以及用
于这一目的的任何文件系统)。
创建一个简单的基于 Ext2fs 的 Ramdisk:
mke2fs -vm0 /dev/ram 4096
mount -t ext2 /dev/ram /mnt
cd /mnt
cp /bin, /sbin, /etc, /dev ... files in mnt
cd ../
umount /mnt
/dd if=/dev/ram bs=1k count=4096 of=ext2ramdisk
mke2fs 是用于在任何设备上创建 ext2 文件系统的实用程序 — 它创建超级块、索引
节点以及索引节点表等等。
在上面的用法中,/dev/ram 是上面构建有 4096 个块的 ext2 文件系统的设备。然后,
将这个设备(/dev/ram)挂装在名为 /mnt 的临时目录上并且复制所有必需的文件。一旦
复制完这些文件,就卸装这个文件系统并且设备(/dev/ram)的内容被转储到一个文件
(ext2ramdisk)中,它就是所需的 Ramdisk(Ext2 文件系统)。
上面的顺序创建了一个 4 MB 的 Ramdisk,并用必需的文件实用程序来填充它。
一些要包含在 Ramdisk 中的重要目录是:
/bin — 保存大多数象 init、busybox、shell、文件管理实用程序等二进制文件。
/dev — 包含用在设备中的所有设备节点
/etc — 包含系统的所有配置文件
/lib — 包含所有必需的库,如 libc、libdl 等
2. 日志闪存文件系统JFFS2
瑞典的 Axis Communications 开发了最初的 JFFS,Red Hat 的 David Woodhouse 对
它进行了改进。 第二个版本,JFFS2,作为用于微型嵌入式设备的原始闪存芯片的实际文
件系统而出现。JFFS2 文件系统是日志结构化的,这意味着它基本上是一长列节点。每个
节点包含有关文件的部分信息 — 可能是文件的名称、也许是一些数据。相对于 Ext2fs,
JFFS2 因为有以下这些优点而在无盘嵌入式设备中越来越受欢迎:
(1) JFFS2 在扇区级别上执行闪存擦除/写/读操作要比 Ext2 文件系统好。
(2) JFFS2 提供了比 Ext2fs 更好的崩溃/掉电安全保护。当需要更改少量数据时,Ext2
文件系统将整个扇区复制到内存(DRAM)中,在内存中合并新数据,并写回整个扇区。这
意味着为了更改单个字,必须对整个扇区(64 KB)执行读/擦除/写例程 — 这样做的效
率非常低。要是运气差,当正在 DRAM 中合并数据时,发生了电源故障或其它事故,那么
将丢失整个数据集合,因为在将数据读入 DRAM 后就擦除了闪存扇区。JFFS2 附加文件而
不是重写整个扇区,并且具有崩溃/掉电安全保护这一功能。
这可能是最重要的一点:JFFS2 是专门为象闪存芯片那样的嵌入式设备创建的,所以
它的整个设计提供了更好的闪存管理。
因为本文主要是写关于闪存设备的使用,所以在嵌入式环境中使用 JFFS2 的缺点很
少:
当文件系统已满或接近满时,JFFS2 会大大放慢运行速度。这是因为垃圾收集的问题。
3. YAFFS 文件系统
YAFFS,Yet Another Flash File System,是一种类似于JFFS/JFFS2 的专门为Flash
设计的嵌入式文件系统。与JFFS 相比,它减少了一些功能,因此速度更快、占用内存更少。
YAFFS 和JFFS 都提供了写均衡,垃圾收集等底层操作。它们的不同之处在于:
(1)、JFFS 是一种日志文件系统,通过日志机制保证文件系统的稳定性。YAFFS 仅仅借鉴的空间(以解压缩之后的形式存在),这违背了嵌入式环境下尽量节省资源的要求。
(2)、JFFS 中使用多级链表管理需要回收的脏块,并且使用系统生成伪随机变量决定要回
收的块,通过这种方法能提供较好的写均衡,在YAFFS 中是从头到尾对块搜索,所以在垃
圾收集上JFFS 的速度慢,但是能延长NAND 的寿命。
(3)、JFFS 支持文件压缩,适合存储容量较小的系统;YAFFS 不支持压缩,更适合存储容
量大的系统。
YAFFS 还带有NAND 芯片驱动,并为嵌入式系统提供了直接访问文件系统的API,用户
可以不使用Linux 中的MTD 和VFS,直接对文件进行操作。NAND Flash 大多采用MTD+YAFFS
的模式。MTD( Memory Technology Devices,内存技术设备)是对Flash 操作的接口,提
供了一系列的标准函数,将硬件驱动设计和系统程序设计分开。
4. tmpfs
当 Linux 运行于嵌入式设备上时,该设备就成为功能齐全的单元,许多守护进程会在
后台运行并生成许多日志消息。另外,所有内核日志记录机制,象 syslogd、dmesg 和
klogd,会在 /var 和 /tmp 目录下生成许多消息。由于这些进程产生了大量数据,所以允
许将所有这些写操作都发生在闪存是不可取的。由于在重新引导时这些消息不需要持久存
储,所以这个问题的解决方案是使用 tmpfs。
tmpfs 是基于内存的文件系统,它主要用于减少对系统的不必要的闪存写操作这一唯
一目的。因为 tmpfs 驻留在 RAM 中,所以写/读/擦除的操作发生在 RAM 中而不是在闪
存中。因此,日志消息写入 RAM 而不是闪存中,在重新引导时不会保留它们。tmpfs 还使
用磁盘交换空间来存储,并且当为存储文件而请求页面时,使用虚拟内存(VM)子系统。
tmpfs 的优点包括:
(1) 动态文件系统大小 — 文件系统大小可以根据被复制、创建或删除的文件或目录的数
量来缩放。使得能够最理想地使用内存。
(2) 速度 — 因为 tmpfs 驻留在 RAM,所以读和写几乎都是瞬时的。即使以交换的形式存
储文件,I/O 操作的速度仍非常快。
tmpfs 的一个缺点是当系统重新引导时会丢失所有数据。因此,重要的数据不能存储
在 tmpfs 上。
5. cramfs 的特点
在嵌入式的环境之下,内存和外存资源都需要节约使用。如果使用RAMDISK 方式来使
用文件系统,那么在系统运行之后,首先要把外存(Flash)上的映像文件解压缩到内存中,
构造起RAMDISK 环境,才可以开始运行程序。但是它也有很致命的弱点。在正常情况下,
同样的代码不仅在外存中占据了空间(以压缩后的形式存在)使用cramfs 就是一种解决这个问题的方式。cramfs 是一个压缩式的文件系统,它并
不需要一次性地将文件系统中的所有内容都解压缩到内存之中,而只是在系统需要访问某
个位置的数据的时侯,马上计算出该数据在cramfs 中的位置,将其实时地解压缩到内存之
中,然后通过对内存的访问来获取文件系统中需要读取的数据。cramfs 中的解压缩以及解
压缩之后的内存中数据存放位置都是由cramfs 文件系统本身进行维护的,用户并不需要了
解具体的实现过程,因此这种方式增强了透明度,对开发人员来说,既方便,又节省了存
储空间。
cramfs 拥有以下一些特性:
1) 采用实时解压缩方式,但解压缩的时侯有延迟。
2) cramfs 的数据都是经过处理、打包的,对其进先写操作有一定困难。所以cramfs
不支持写操作,这个特性刚好适合嵌入式应用中使用Flash 存储文件系统的场合。
3) 在cramfs 中,文件最大不能超过16MB。
4) 支持组标识(gid),但是mkcramfs 只将gid 的低8 位保存下来,因此只有这8 位是
有效的。
5)支持硬链接。但是cramfs 并没有完全处理好,硬链接的文件属性中,链接数仍然为
1.
6) cramfs 的目录中,没有“.”和“..”这两项。因此,cramfs 中的目录的链接数通
常也仅有一个。
cramfs 中,不会保存文件的时间戳(timestamps)信息。当然,正在使用的文件由于
inode 保存在内存中,因此其时间可以暂时地变更为最新时间,但是不会保存到cramfs 文
件系统中去。
当前版本的cramfs 只支持PAGE_CACHE_SIZE 为4096 的内核。因此,如果发现cramfs
不能正常读写的时侯,可以检查一下内核的参数设置。
使用cramfs
可以从http://sourceforge.net/projects/cramfs/下载cramfs-1.1.tar.gz。然后执
行
tar zxvf cramfs-1.1.tar.gz
进入解包之后生成cramfs-1.1 目录,执行编译命令:
Make
编译完成之后,会生成mkcramfs 和cramfsck 两个工具,其中cramfsck 工具是用来创
建cramfs 文件系统的,而mkcramfs 工具则用来进行cramfs 文件系统的释放以及检查。
下面是mkcramfs 的命令格式:
mkcramfs [-h] [-e edition] [-i file] [-n name] dirname outfile
mkcramfs 的各个参数解释如下:
-h:显示帮助信息
-e edition:设置生成的文件系统中的版本号
-i file:将一个文件映像插入这个文件系统之中(只能在Linux2.4.0 以后的内核版本
中使用)
了日志系统的思想,不提供日志机能,所以稳定性不如JAFFS,但是资源占用少。
-n name:设定cramfs 文件系统的名字
dirname:指明需要被压缩的整个目录树
outfile:最终输出的文件
cramfsck 的命令格式:
cramfsck [-hv] [-x dir] file
cramfsck 的各个参数解释如下:
-h:显示帮助信息
-x dir:释放文件到dir 所指出的目录中
-v:输出信息更加详细
file:希望测试的目标文件