1 文件系统 文件系统是一个操作系统中最重要的部分之一,它为操作系统提供了一种结构化存储和管理数据的方式。文件系统的主要功能是对数据的物理存储进行管理,并向用户提供对数据的访问接口。用户程序建立在文件系统上,通过文件系统访问数据,而不需要直接对物理存储设备进行操作。 最初的操作系统一般都只支持单一的一种文件系统,并且文件系统和操作系统内核紧密关联在一起,而Linux操作系统的文件系统结构是树状的,在根目录“/’下有许多子目录,每个目录都可以采用各自不同的文件系统类型。Linux中的文件不仅指的是普通的文件和目录,而且将设备也当作一种特殊的文件,因此,每种不同的设备,从逻辑上都可以看成是一种不同的文件系统。 在Linux操作系统中,为了支持多种不同的文件系统,采用了虚拟文件系统(VFS,Visual Filesystem Switch)技术,虚拟文件系统是对多种实际文件系统的共有功能的抽象,它屏蔽了各种不同文件系统在实现细节上的差异,为用户程序提供了统一的、抽象的、标准的接口对文件系统进行访问,如open(),read(),write()等。这样,用户程序就不需要关心所操作的具体文件是属于哪种文件系统,以及这种文件系统是如何设计与实现的,对所有文件的访问方式都是完全相同的。VFS与实际文件系统的关系如图1所示。 2 Flash存储器 由于具有高可靠性、高存储密度、低价格、非易失、擦写方便等优点,Flash存储器取代了传统的EPROM 和EEPROM,在嵌入式系统中得到了广泛的应用。Flash存储器可以分为若干块,每块义由若干页组成,对Flash的擦除操作以块为单位进行,而读和写操作以页为单位进行。Flash存储器在进行写入操作之前必须先擦除目标块。根据所采用的制造技术不同,Flash存储器主要分为Nor Flash和Nand Flash两种。 1)Nor Flash。 Nor Flash通常容量较小,其主要特点是 片内执行(XIP,eXecute In Place),就是指程序代码可以直接在Flash内运行,而不需要将代码读取到RAM中再执行。Nor Flash具有RAM接口,易于访问,它的缺点是擦除电路复杂,写速度和擦除速度都比较慢,最大擦写次数约10万次,典型的块大小是128kB。
2)Nand Flash。 Nand Flash通常容量较大,具有很高的存储密度,从而降低了单位价格。Nand Flash的块尺寸较小,典型大小为8kB,擦除速度快,使用寿命也更长,最大擦写次数可以达到100万次,但是其访问接口是复杂的I/O口。并且坏块和位反转现象较多,对驱动程序的要求较高。由于Nor Flash和Nand FIash各具特色,因此它们的用途也各不相同,Nor Flash一般用来存储体积较小的代码,而Nand Flash则用来存放大体积的数据。 3 Flash文件系统 在嵌入式系统中,也可以在Flash上运行传统的文件系统,如ext2等,但是这类文件系统没有考虑Flash存储器的物理特性和使用特点,例如:Flash存储器中各个块的最大擦除次数是有限的,如果能够均匀地使用各个块,就能延长Flash的整体寿命,这就需要磨损均衡的功能;为了提高Flash存储器的利用率,还应该有对存储空间的碎片收集功能;在嵌入式系统中,要考虑出现系统意外掉电的情况,所以文件系统应该有掉电保护的功能,保证系统在出现意外掉电时也不会丢失数据。因此在Flash存储设备上,采用专门针对Flash存储器的要求而设计的JFFS2(Journaling Flash File System Version 2)文件系统更为合适。
3.1 日志文件系统 JFFS2是一种日志文件系统。在日志文件系统中,所有文件系统的内容变化,如写文件操作等,都被记录到一个日志中,每隔一段时间,文件系统会对文件的实际内容进行更新,然后删除这部分日志,重新开始记录。如果对文件内容的变更操作由于系统出现意外而中断,如系统掉电等,则系统重新启动时,会根据日志恢复中断以前的操作,这样系统的数据就更加安全,文件内容将不会因为系统出现意外而丢失。
3.2 MTD驱动程序 JFFS2 建立在MTD(Memory Technology Devices)技术的基础上,MTD是专门为访问Flash存储设备而设计的Linux子系统,提供了对Flash操作的一系列标准接口,能更好地支持对Flash的擦除和读写操作。通过MTD技术,可以将硬件驱动设计和系统程序设计分开。为了使用JFFS2文件系统,需要把MTD子系统编译到内核中,MTD子系统提供MTD_CHAR和MTD_BLOCK这两个模块用于对Flash的访问,MTD_CHAR将Flash表现为字符设备,与其关联的设备文件是/dev/mtd0等,MTD_BLOCK将Flash表现为块设备,与其关联的设备文件是/dev/mtdblock0等;JFFS2文件系统就建立在MTD_BLOCK模块的基础之上。
3.3 JFFS2文件系统 JFFS(Journaling Flash File System)是瑞典的Axis Communications公司专门针对嵌入式系统中的Flash存储器的特性而设计的一种日志文件系统。Redhat公司的David Woodhouse在JFFS的基础上进行了改进,从而发布了JFFS2(Journaling Flash File System Version 2)。和JFFS相比,JFFS2支持更多节点类型,提高了磨损均衡和碎片收集的能力,增加了对硬链接的支持。JFFS2还增加了数据压缩功能,这更利于在容量较小的Flash中使用。和传统的Linux文件系统如ext2相比,JFFS2处理擦除和读写操作的效率更高,并且具有完善的掉电保护功能,使存储的数据更加安全。在嵌入式系统中使用JFFS2文件系统的缺点很少,只是当文件系统快要满时,JFFS2会放慢运行速度,这是由于碎片收集的原因。 4 JFFS2文件系统的实现 文中所用的目标板CPU是韩国Samsung公司的S3C2410X,这是一种基于ARM920T核的嵌入式微处理器,所用的Flash存储器是Intel公司Strata Flash系列中的E28F128,这是一种典型的Nor Flash芯片,容量为16MB。文中所采用的操作系统内核版本是Linux-2.4.18-rmk7-pxal,这个版本在嵌入式系统中有着广泛的应用。 4.1 裁减内核 首先进入drivers/mtd/maps/目录下,编写Flash芯片的map文件,例如文件名为s3c2410-strata.c。在map文件中需要定义Flash的基地址、大小、宽度、分区表、读写函数、初始化和释放函数等。其中分区表的一个例子如下: static struct mtd_partition s3c2410_partitions[]= { { name:"bootloader", size:0x00030000, offer:0x0, mask_flags:MTD_WRITEABLE, }, { name:"kernel", size:0x000d0000, offset:MTDPART_OFS_APPEND, mask_flags:MTD_WRITEABLE, }, { name:"rootfs", size:MTDPART_SIZ_FULL, offset:MTDPART_OFS_APPEND, } }; 这里将Flash分成3个分区,分别存放引导装载程序(Bootloader)、内核和根文件系统。mask_flags:MTD_WRITEABIE表示分区是只读的;MTDPART_OFS_APPEND表示分区位置紧挨着上一个分区;MTDPART_SIZ_FULL表示占用剩余的全部空间。文中将JFFS2文件系统的映像存放在第3个分区上,作为系统的根文件系统。 然后修改Makefile文件,在其中加入以下语句: obj -$(CONFIG_MID_S3C2410) + = s3c2410-strata.O 再修改Config.in文件,在适当位置加入以下语句: dep_tristate 'Intel Strata Flash device mapped On S3C2410' CONFIG_MTD_S3C2410 CONFIG_MTD_CFI 然后回到Linux源码目录下,运行make menuconfig对操作系统内核进行配置与裁减,要在Intel E28F128 Flash上使用JFFS2文件系统,要特别注意以下两个选项: 1)在“Memory Technology Devices(MTD)”选项中选择: <*>Memory Technology Device(MTD)support <*>MTD partitioning support <*>Cashing block device access to MTD devices RAM/ROM/Flash chip drivers---> <*> Detect flash chips by Common Flash Interface(CFI) probe <*> Support for Intel/Sharp flash chips Mapping drivers for chip access---> <*> CFI Flash device in physical memory map(0)physical start address of flash mapping (1000000)Physical length of flash mapping(2)Buswidthin octets <*> Intel StrataFlash device mapped On S3C2410 这里设置了Flash芯片的起始地址、大小以及宽度,比如:起始地址为“0”,大小为“1000000”,即16MB,宽度为“2”,即16字节。然后选中自己加入的“Intel Strata Flash device mapped on S3C2410”这一项。 2)在“File systems”选项中选择: <*>Joumalling Flash File System v2(JFFS2)support 对于其他功能,可根据自己的实际情况,进行裁减,然后保存退出,接下来编译出操作系统内核映像。
4.2 制作根文件系统映像 要制作根文件系统的映像,可以借助于BusyBox生成所需的大部分文件,然后自己再补充建立/dev,/proc,/etc等目录,在dev目录下建立设备文件,例如: $mknod dev/console C 5 1 目录和文件建立完成后,使用mkfs.jffs2工具产生文件系统映像: $ ./mkfs.jffs2 -e0x20000 -d./rootfsdir -ojffs2.img 其中-e 0x20000表示擦除块的大小为128kB;-d表示文件系统所在的目录;-o表示文件系统映像名。
4.3 烧写并运行 根据分配的分区表信息,将Bootloader、内核映像和根文件系统映像分别写入Flash中的指定区域,在Bootloader中设置内核命令行,例如“noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttyS0”,然后引导系统。 5 结束语 JFFS2文件系统是专门针对嵌入式系统中的Flash存储芯片设计的,由于JFFS2自身的特点,适合于在Nor Flash系列芯片上使用,本文以Intel Strata Flash E28F128为例,介绍了在Nor Flash上实现JFFS2文件系统的过程,为嵌入式Linux下的应用程序开发奠定了基础。
|