嵌入式设备上的文件系统优化设计
随着芯片技术的发展,各种处理器的处理能力不断提高,手持智能终端得到极大的普及。嵌入式Linux操作系统在未来的手持智能设备中将扮演着非常重要的角色,使嵌入式Linux的应用和研究不断的深入。
由于Microsoft公司的Windows操作系统占据了桌面操作系统绝大多数份额,而手持智能设备与PC机的数据交换又在所难免,因此,绝大多数的大容量嵌入式智能设备必须采用与PC机兼容的FAT/FAT32文件系统。随着便携式硬盘的应用,FAT32在嵌入式硬盘上已成为主流的格式。
同时,随着CPU处理能力的提高,面向存储的应用需求在手持智能设备上也随着不断增长,文件系统的访问性能将是未来的手持设备非常关键的因素。然而,当硬盘在手持智能设备上应用时,由于硬盘访问的高耗能特性,对于手持设备的设计构成了极大的挑战。而硬盘的能耗又与读写访问的时间成正比,从节能的角度出发,系统设计者同样希望在单位时间内读取更多内容,以减少硬盘访问时间从而达到节能的目的。因此,在Linux上的FAT32的优化实现成为非常迫切的需求。
1 Linux中FAT32文件系统读操作分析
1.1 虚拟文件系统与FAT32[1-2]
Linux系统中的虚拟文件系统VFS(Virtual File System)是一个非常强大的机制,其设计思路是在内核中提供一个文件系统框架,包括接口函数集、管理用的数据结构以及各种缓存机制。VFS提供上下两个方面的接口,上层接口是提供给I/O系统的用户使用的,包括应用程序和内核的其他管理模块,通过该接口可使I/O系统(文件、设备、网络等)完成如打开、关闭、读、写等;下层接口是提供给真实文件系统的,VFS支持的每个真实文件系统都要通过这个接口来实现。通过这种机制,Linux将系统存在的各种真实文件系统(如EXT2/EXT3、FAT/FAT32、JFFS/JFFS2等)以及设备文件都统一到一种操作中,以此来实现系统的管理与调度。
FAT(File Allocation Table)文件系统是Microsoft公司推出的广泛使用在Dos、Windows 9X、Windows 2000以及Windows XP系统中。由于Windows系列的操作系统的普及,其FAT文件系统被人们所广泛熟悉和应用。当前针对大容量硬盘,FAT32文件系统占据了主要的地位。在FAT32文件系统中,以下三个概念与文件的组织密切相关:
扇区(Sector): 数据存取的最小物理单位。
簇(Cluster):文件最小分配单位,与分区大小、文件系统相关。
逻辑扇区(Logic Sector):在文件系统实现中,为了优化和统一设计所定义的读写长度。
1.2 文件读在内核中的实现
以读操作为例,通过Linux系统中VFS的作用,从用户空间对FAT32的操作,系统可以抽象成从fread( )映射到内核函数do_generic_file_read( )来完成具体的文件读操作。在文件/μCLinux/linux-2.4.x/mmnommu/filemap.c中存在这个接口实现的原型。虽然这类接口并不是基本的,但正如大多数文件系统的实现,FAT32就是通过这类接口来实现文件的各种操作。
图1描述了函数do_generic_file_read( )的实现原理。从函数入口处获得目标内容的文件描述指针,从而获得文件入口。通过分析描述符inode以及当前状态,系统获得预读read_ahead的大小,进行相应的计算,获得所需要获取的目标内容Page页索引以及offset偏移量。然后发起预读的指令,并等待获得相应的Page内容后,将其拷贝到buffer中进行组织,并提供上层程序磁盘文件在内存中的映像。
1.3 文件预读机制与Page读[1-4]
在do_generic_file_read的实现中,磁盘读动作实际是在预读read_ahead中完成的,即预读机制。这是由于Linux系统为了获得更高的性能以及充分利用CPU处理能力,VFS设计中做了一层buffer/cache缓冲。当系统发现buffer/cache中有即将要访问的内容缺失时,系统将发起一次预读请求。下层文件系统根据寻找CPU以及总线的空闲状态,执行具体的预读机制。这样,上下层构成一个异步过程来完成系统的任务,以达到充分利用系统资源的目的。
在考察read_ahead( )的实现中可以发现,实际上read_ahead( )函数的主要功能是根据实际需求不断调用文件系统中的readpage( )函数来完成的。这是由于Linux的内存管理都是按照页(Page)模式进行组织的。也就是说,每次从具体的对象数据存储设备(如硬盘)上读取相应的数据时,将严格按照page的大小进行读取动作。根据一般定义,Page采用4 096B为单位。在Linux上的FAT32实现中,将由fat_readpage( )具体应用实例来实现这个功能。
1.4 Block读实现[3-4]
由于不同的硬件设备存在不同的物理结构,在文件系统格式化时,最基本的存储单元Cluster的大小是不同的。如通常能够见到的有512B、1KB等。也就是说,实际文件的存储是按照不同的目标存储设备划分为不同的块来存储的。在文件系统实现中,为了兼容不同的目标系统与硬件设备,在FAT文件系统中的Page读动作的实现中,引入了一个Block概念,即根据具体文件描述,按照Block大小完成整个Page的读命令。
在μCLinux/linux-2.4.x/mmnommu/filemap.c文件中,fat_readpage( )的实现就是根据上述目标进行相应设计的,即通过inode获取相应文件的具体存储信息,然后将Page读转化为按照Block块方式进行读操作。也就是通过反复调用block_read_full_page( )函数来满足最后Page内容的获取。
- 基于FAT16文件系统的嵌入式温度记录器(05-30)
- SPI Flash M25P32 的TFFS文件系统的设计与实现(07-04)
- AT24C512中数据的文件系统化管理(10-09)
- 基于ATmega32的SD卡上FAT32文件系统数据读取(10-08)
- 基于STM32处理器的便携式BMP图片解码系统设计(01-07)
- 基于ARM9和μC/OS-II的SD卡文件系统设计与实现(07-08)