文件系统结构分析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
文件系统结构分析
1 嵌入式文件系统
1.1嵌入式文件系统体系结构
在嵌入式系统中,文件系统是嵌入式系统的一个组成模块,它是作为系统的一个可加载选项提供给用户,由用户决定是否需要加载它。
同时,它还需要满足结构紧凑、代码量小、支持多种存储设备、可伸缩、可剪裁、可移植等特点。
基于上面的要求,嵌入式文件系统在设计和实现时就要把它作为一个独立的模块来整体考虑。
特别是对文件系统内部资源的管理要做到独立性。
由于嵌入式文件系统是作为嵌入式系统的一个可选加载项提供给用户的,当用户针对其应用的特殊要求对嵌入式系统进行配置时没有选择加载文件系统,但是用户还是需要使用到系统I/O。
由于这种情况的出现就决定了嵌入式系统中的文件系统不再具有I/O设备的管理功能。
系统I/O的管理和使用接口的提供将由I/O管理模块完成,文件系统作为一个独立的自包含模块存在。
基于以上考虑,嵌入式文件系统的体系结构如图1所示。
图1 嵌入式文件系统体系结构
在嵌入式文件系统的最上层是文件系统API。
文件系统的一切功能都是通过
这一层提供给用户的。
同时,在整个文件系统中也只有这一层对用户是可见的。
在这一层中所提供的所有功能接口都将严格的遵循POSIX标准。
文件系统核心层是实现文件系统主要功能的模块。
在这一层中,文件系统要把用户的功能操作转化成对文件系统的抽象对象的操作。
这些操作将通过下面的功能模块最终落实到物理介质上面。
如果文件系统需要支持多种具体的文件系统格式的话,这一层还可以进一步细分成虚拟文件系统和逻辑文件系统。
块高速缓存的存在是为了提高文件系统的性能。
在这一层中缓存着以前访问过的块设备数据。
文件系统通过一定的算法来高效的管理这些数据,以提高缓冲的性能。
同时,它的存在使下层的数据操作对上层的文件操作透明,提高了文件系统的模块性。
1.2嵌入式文件系统体系的功能与特点
文件系统是操作系统的重要组成部分,用于控制对存储设备的存取。
它提供对文件和目录的分层组织形式、数据缓冲(对于实时系统,允许绕过缓冲)以及对文件存取权限的控制。
嵌入式系统所使用的文件系统除了要提供通用文件系统的功能外,还由于嵌入式操作系统的特殊性而具有其自身的一些特点。
嵌入式文件系统的设计应该满足如下目标:
1.实现按名存取。
和桌面操作系统类似,用户对文件的操作是通过其“文件名”来完成的。
因此,用户只需知道待操作文件的文件名,就可以方便的访问数据,而不必关心文件在物理设备上是如何存放的,以及如何对文件的打开、关闭操作进行处理等细节。
所有与文件相关的管理工作都由文件系统组件隐式完成。
2.与实时系统相适应。
嵌入式应用大多数都具有实时性需求。
实时系统不仅要求计算结果地准确无误,而且要求特定的指令要在限定的时间内完成,这就对文件系统提出了很高的要求。
在通用操作系统中,往往采取分页和虚拟存储器管理的机制来满足规定的指令时间。
然而嵌入式实时操作系统一般都不具有虚拟存储器管理机制,且各种外部设备的性能差异较大,控制文件系统的实时性变得非常困难。
为了尽可能提高文件系统的实时性,除了选取高速存储介质作为嵌入式系统的外设外,还应该根据设备的特点设置一定大小的高速缓冲,以提高数据存取的相应速度。
3.支持多任务环境。
面对日益复杂的计算环境,应用常常采取“分而治之”的方法,将解决方案划分为多个任务,每个任务完成相对单一的功能。
实时操作系统的设计目标之一就是对多任务的支持。
从应用的层面上看,多任务可以对文件进行并发读操作,在实时内核进程间同步与通信机制支持下进行写操作。
此外,文件系统内部实现也应该具备较好的可重入性,即利用同步机制对全局数据结构
进行必要的保护。
4.支持多种逻辑文件系统标准。
随着操作系统技术的发展,出现了多种成熟的桌面文件系统标准,如Windows下的FAT系列,Linux中的ext系列等。
将这些成熟标准引入嵌入式领域的同时,如何在各种不同标准的存储介质中互通数据,也是文件系统设计的考虑因素。
应用程序应该使用同一套系统调用操作文件,而无需考虑面对的文件系统标准和存储介质。
因此,文件系统的设计时应该引入文件操作抽象层,通过虚拟接口访问文件系统,才能使得这种协作性和通用性成为可能。
5.接口标准的开放性和可移植性。
文件系统对外提供的系统调用是应用与系统的交互接口。
为了增加接口的开放性和可移植性,嵌入式文件系统的系统调用必须符合一定的标准和规范。
可移植操作系统接口(Portable Operating System Interface,POSIX)是一种由IEEE指定的信息标准,它为程序员提供了一种严格定义的固定框架,以获得源码级的软件可移植性;换言之,为一个POSIX标准兼容的操作系统编写的程序,可以很容易的移植到其它POSIX标准的操作系统上编译执行。
2 FatFs文件系统体系结构
图2 FatFs文件系统体系结构
在FatFs的最上层是文件系统API。
文件系统的一切功能都是通过这一层提
供给用户的。
同时,在整个FatFs文件系统中也只有这一层对用户是可见的。
在这一层中所提供的所有功能接口都将遵循POSIX标准。
文件系统核心层是实现文件系统主要功能的模块。
在这一层中,文件系统要把用户的功能操作转化成对物理介质的抽象对象的操作。
这些操作将通过下面的功能模块最终落实到物理介质上面。
如果文件系统需要支持多种具体的文件系统格式的话,这一层还可以进一步细分成虚拟文件系统和逻辑文件系统。
DISK I/O模块的存在是为了提高文件系统的性能,通过缓存提高数据读写速度,文件系统通过一定的管理算法来高效的管理这些数据,以提高缓冲的性能。
而RTC提供了整个系统时间的标尺,是实时操作系统的必要组成部分。
3 FatFs文件系统标准
3.1 FatFs文件系统组成
FatFs源自Microsoft所推出的WinCe文件系统,因其具有Fat文件系统的高度兼容性,能广泛应用于嵌入式系统尤其是移动性要求高的设备中。
本课题FatFs选择FAT16系统,故拥有相同的FAT16结构
FAT16是Microsoft较早推出的文件系统,具有高度兼容性,目前仍然广泛应用于个人电脑尤其是移动存储设备中,FAT16简单来讲由图3所示的6部分组成(主要是前5部分)。
1扇区
31个扇
区
实际情况取
大小
同FAT1 第2簇
不足一
簇
保留扇区┗━━━━━━━━数据区━━━━━┛
引导扇区DBR区(DOS BOOT RECORD)即操作系统引导记录区的意思,也称为
启动扇区。
它记录了存储卡的所有重要信息,一共512个字节,其结构如表1所示:
图3 FatFs的组成
FAT16在DBR之后没有留有任何保留扇区,其后紧随的便是FAT表。
FAT表是FAT16用来记录磁盘数据区簇链结构的。
FAT表实际上是一个数据表,以2个字节为单位,我们暂将这个单位称为FAT 记录项,通常情况其第1、2个记录项(前4个字节)用作介质描述。
从第三个记录项开始记录除根目录外的其他文件及文件夹的簇链情况。
根据簇的表现情况FAT用相应的取值来描述,如表3:
表3 FAT表
FAT表记录了磁盘数据文件的存储链表,对于数据的读取而言是极其重要的,以至于Microsoft为其开发的FAT文件系统中的FAT表创建了一份备份,就是我
们看到的FAT2。
FAT2与FAT1的内容通常是即时同步的,也就是说如果通过正常的系统读写对FAT1做了更改,那么FAT2也同样被更新。
如果从这个角度来看,系统的这个功能在数据恢复时是个天灾。
FAT将磁盘空间按一定数目的扇区为单位进行划分,这样的单位称为簇。
通常情况下,每扇区512字节的原则是不变的。
簇的大小一般是2n (n为整数)个扇区的大小,像512B,1K,2K,4K,8K,16K,32K,64K。
实际中通常不超过32K。
分区的大小和簇的取值是有关系的,如表4:
FAT16 DBR参数的偏移0x11处记录了根目录所占扇区的数目。
偏移0x16记录了FAT表所占扇区的数据。
偏移0x10记录了FAT表的副本数目。
系统在得到这几项参数以后,就可以确定数据区的开始扇区偏移了。
FAT16文件系统从根目录所占的32个扇区之后的第一个扇区开始以簇为单位进行数据的处理,这之前仍以扇区为单位。
对于根目录之后的第一个簇,系统并不编号为第0簇或第1簇 (可能是留作关键字的原因吧),而是编号为第2簇,也就是说数据区顺序上的第1个簇也是编号上的第2簇。
3.2 FAT的目录结构
FAT文件系统的目录结构其实是一颗有向的从根到叶的树,这里提到的有向是指对于FAT分区内的任一文件(包括文件夹),均需从根目录寻址来找到。
可以这样认为:目录存储结构的入口就是根目录。
FAT文件系统根据根目录来寻址其他文件(包括文件夹),故而根目录的位置必须在磁盘存取数据之前得以确定。
FAT文件系统就是根据分区的相关DBR参数与DBR中存放的已经计算好的FAT表(2份)的大小来确定的。
格式化以后,跟目录的大小和位置其实都已经确定下来了:位置紧随FAT2之后,大小通常为32个扇区。
根目录之后便是数据区第2簇。
FAT文件系统的一个重要思想是把目录(文件夹)当作一个特殊的文件来处
理,FAT32甚至将根目录当作文件处理,在FAT16中,虽然根目录地位并不等同于普通的文件或者说是目录,但其组织形式和普通的目录(文件夹)并没有不同。
FAT分区中所有的文件夹(目录)文件,实际上可以看作是一个存放其他文件(文件夹)入口参数的数据表。
所以目录的占用空间的大小并不等同于其下所有数据的大小,但也不等同于0。
通常是占很小的空间的,可以看作目录文件是一个简单的二维表文件。
其具体存储原理是:
不管目录文件所占空间为多少簇,一簇为多少字节。
系统都会以32个字节为单位进行目录文件所占簇的分配。
这32个字节以确定的偏移来定义本目录下的一个文件(或文件夹)的属性,实际上是一个简单的二维表。
表5 FAT16目录项32个字节的含义
对上表中的一些取值进行说明:
(1)、对于短文件名,系统将文件名分成两部分进行存储,即主文件名+扩展名。
0x0~0x7字节记录文件的主文件名,0x8~0xA记录文件的扩展名,取文件名中的ASCII码值。
不记录主文件名与扩展名之间的"." 主文件名不足8个字符以空白符(20H)填充,扩展名不足3个字符同样以空白符(20H)填充。
0x0偏移处的取值若为00H,表明目录项为空;若为E5H,表明目录项曾被使用,但对应的文件或文件夹已被删除。
(这也是误删除后恢复的理论依据)。
文件名中的第一个
字符若为“.”或“..”表示这个簇记录的是一个子目录的目录项。
“.”代表当前目录;“..”代表上级目录(和我们在dos或windows中的使用意思是一样的,如果磁盘数据被破坏,就可以通过这两个目录项的具体参数推算磁盘的数据区的起始位置,猜测簇的大小等等,故而是比较重要的)
(2)、0xB的属性字段:可以看作系统将0xB的一个字节分成8位,用其中的一位代表某种属性的有或无。
这样,一个字节中的8位每位取不同的值就能反映各个属性的不同取值了。
如00000101就表示这是个文件,属性是只读、系统。
(3)、0xC~0x15在原FAT16的定义中是保留未用的。
在高版本的WINDOWS系统中有时也用它来记录修改时间和最近访问时间。
那样其字段的意义和FAT32的定义是相同的,见后边FAT32。
(4)、0x16~0x17中的时间=小时*2048+分钟*32+秒/2。
得出的结果换算成16进制填入即可。
也就是:0x16字节的0~4位是以2秒为单位的量值;0x16字节的5~7位和0x17字节的0~2位是分钟;0x17字节的3~7位是小时。
(5)、0x18~0x19中的日期=(年份-1980)*512+月份*32+日。
得出的结果换算成16进制填入即可。
也就是:0x18字节0~4位是日期数;0x18字节5~7位和0x19字节0位是月份;0x19字节的1~7位为年号,原定义中0~119分别代表1980~2099,目前高版本的Windows允许取0~127,即年号最大可以到2107年。
(6)、0x1A~0x1B存放文件或目录的表示文件的首簇号,系统根据掌握的首簇号在FAT表中找到入口,然后再跟踪簇链直至簇尾,同时用0x1C~0x1F处字节判定有效性。
就可以完全无误的读取文件(目录)了。
(7)、普通子目录的寻址过程也是通过其父目录中的目录项来指定的,与数据文件(指非目录文件)不同的是目录项偏移0xB的第4位置1,而数据文件为0。
对于整个FAT分区而言,簇的分配并不完全总是分配干净的。
如一个数据区为99个扇区的FAT系统,如果簇的大小设定为2扇区,就会有1个扇区无法分配给任何一个簇。
这就是分区的剩余扇区,位于分区的末尾。
有的系统用最后一个剩余扇区备份本分区的DBR,这也是一种好的备份方法。