自己设计自己的文件系统

时间:2022-04-18 20:08:54
文件系统是某些操作系统必然包含的模块,对系统中存储介质的访问以同一的系统接口进行管理,完成read ,write,ioctl等操作。
按照实现方式,可分为传统的单机版的文件系统和网络分布式的文件系统。
分布式文件系统通常应用网络技术和协议,将分散的各个数据资源进行同一管理的系统形式。
嵌入式操作系统上的文件系统,或者说传统的文件系统一般是单一的本地数据管理系统。例如常用的FAT Ext2 yaffs 等。
这里说的就是这种传统的文件系统。

目前有许多成熟的和开源的文件系统,通用型的或者针对具体应用场合的。根据自己系统的需要选取成熟的文件系统,是最可取的一种方式。但是有时为了提高系统性能,往往根据自己的需要对文件系统进行改进甚至自己实现一个理想的文件系统,也是非常必要的。这里就是结合文件系统实现的基本原理,结合一个针对流媒体存储文件系统的应用例子,来描述一下自己实现的文件系统的原理,希望能够起到抛砖引玉的作用。

一般的存储介质包括hdd, flash,eeprom,ram...... 根据不同硬件介质的特性,在保证正确可靠,高性能的情况下,都有特定的文件系统支持。这里以在hdd块设备上实现文件系统为例。其实文件系统完全可以屏蔽底层驱动接口,但不同的硬件特性,可以有特定的文件系统,还是有点区别,这里就不详细说明。

就如其他模块设计一样,首先要保证系统正确可靠,然后是想法提高系统性能。在这样的设计思想下,如何针对自己对文件访问的应用,设计出合理可靠的存储结构和高效的访问机制,是系统设计的关键。

一般说,在介质加载的起始地方,肯定要包含文件系统的基本信息(有的还有boot信息,包括分区信息)。在此基础上,建立起文件系统目录结构。由驱动提供的访问函数,根据目录文件的信息,访问相应的数据节点。访问的基本单位是簇(块),包含多个sector。.基本访问单元大小和每个sector大小,可以根据需要进行设置。这个往往根据数据存储情况和访问情况,在sector浪费和访问费用之间进行平衡,也就是空间和时间平衡的关系。

在流媒体应用领域,在硬盘上对数据的存储一般一次性存储是比较大的。针对这个特点,可以设计出自己的一个流媒体文件系统。

将硬盘分区上划分为supper block(文件系统信息表)+FAT(文件分配表)+Data(数据区)。以sector为最小单位(一般512bytes),
|supper block| FAT |data
supper block占用了一个sector. 其包含了文件系统类型,版本号;本分区的大小;文件分配表大小;申请单元大小;
根目录index; 分配表个数;参考分配表index; 备份supper block lsn; 分配表lsn; 数据区lsn.
当系统mount时,根据supper block 信息,找到参考文件分配表,将参考文件分配表内容拷贝到工作分配表中。其中的原理是,系统可以有多个文件分配表相互备份,至少有2个。一个是参考文件分配表,一个是工作文件分配表。当文件信息更新(用户命令和系统定时更新)完成后,此刻的工作文件分配表信息认为是可靠的,可以将其设置为参考文件分配表,而将原来的参考分配表或者其他的设置为工作分配表,并拷贝完最新数据。这样,能够保证文件分配表数据的完整性。即使在操作过程中有掉电行为,也可以将原来的完整参考分配表恢复回来。
根据root index和文件分配表,找到根目录所在的文件分配信息sector,并可以对出相应的数据,进而建立起目录树。

FAT中包含多个文件(目录)记录。一个记录为一个sector.一个FAT的大小,可以根据实际要用到的文件个数和数据区的大小来设置。一个文件记录里包含本记录的类型(文件,目录,扩展),名称,文件属性(日期,访问权限,所有者),长度,文件节点,父节点,内容sector的lsn,扩展extension记录.根据open传递的文件名称,找到相应的文件FAT记录,进而得到文件节点。根据FAT记录就可以找到数据内容的lsn,进行数据访问了。相应管理也可以根据记录里的其他属性进行工作。其中的内容lsn可以记录多个连续的分配单元给本文件使用。这样适用于碎片比较多的情况。当文件比较大碎片比较多的时候,一个记录不够用,可以再申请一个记录,叫扩展extension记录来继续进行数据申请区的记录管理。这样根据每个文件的FAT记录,就可以找到其名称等属性和数据记录区。

数据区就是一系列的连续(也可以不连续,但要保证基本申请单元大小n*sector)的块区域组成。一般块设备是按sector划分,每块512bytes. 这里的分配空闲管理,是在系统加载时通过扫描每个FAT记录里数据区的使用情况建立的。其每个申请单元情况对应使用情况表的一位来标识。在format时可以根据每个数据块的读情况标识好坏。由于管理数据块使用空闲情况的表是建立在内存中的,所以这个表象不能太大,或者每个管理单元要大些。在流媒体文件,一般是以兆为单位的,所以可以为4M,8M等。有的文件系统,如FAT,将这个结构也放到文件分配表里,存储到硬盘上,在需要时再读出来。

到此,硬盘上用到的数据结构设计完成,完全可以保证数据访问的可靠性和正确性。

还要采取些访问措施,来提高系统访问性能。

首先可以建立一个cache机制,申请一段内存,将最近访问的文件记录放入其中,这样再次访问时,可以从内存中查找记录提高性能。
其次可以建立一个申请窗口机制。就是在为每个文件申请内容sector时,多申请一些在一个window里记录下来。这样再此用到数据sector时,可以快速得到,提高性能。
最后,也是所有块设备访问的基本机制,就是命令队列。将每个访问以命令的方式下发,系统可以根据需要进行QOS或者其他方式进行处理,提高系统对不同命令等级的处理性能。

总之,文件系统实现是离不开文件系统基本原理的,完全可以根据自己的需要来修改,甚至实现。抛开这些神秘的面纱,还原其原来面目。我们也可以做得到。

草草完成,简单阐述,不对之处,望多指出讨论。