笔者最近在自学FAT32系统及其在嵌入式的应用,将学习笔记整理发布。
学习过程中主要参考的资料有:
B站:【纯干货| 超实用!来看Fat32文件系统详细解读——带你一节课掌握FatFS小型文件系统!】https://www.bilibili.com/video/BV1nt4y1x7sx?vd_source=570424ca062fd6ac3ad8245c3d242c68
于振南著:《嵌入式FAT32文件系统设计与实现——基于振南znFAT》
文件系统就是一种在磁盘上管理文件的方法,想了解文件系统,首先需要简要了解一下磁盘的工作原理。
一 磁盘的工作原理
此部分不做深入讨论,简单介绍下磁盘的工作原理,为后面介绍文件系统的内容做个铺垫。
磁盘的工作原理主要参考知乎上这篇文章(磁盘原理介绍 - 知乎 (zhihu.com))。
硬盘结构的示意图如下图所示:
磁头(head):主要就是读取磁盘表面磁方向和改变其方向,每个盘面有一个磁头,它极其贴近地悬浮在盘面上,但是绝对不与盘面接触,否则会损坏磁头和盘面;
磁道(track):磁道是单个盘面上的同心圆,当磁盘旋转时,磁头若保持在一个位置上,则每个磁头都会在磁盘表面划出一个圆形轨迹,这些圆形轨迹就叫做磁道,一个盘面上的磁道可以有成千上万个。相邻磁道之间并不是紧挨着的,这是因为磁化单元相隔太近时磁性会产生相互影响,同时也为磁头的读写带来困难。
柱面(cylinder):在有多个盘片构成的盘组中,由不同盘片的面,但处于同一半径圆的多个磁道组成的一个圆柱面。
扇区(sector):磁盘上的每个磁道被等分为若干个弧段,这些弧段便是硬盘的扇区(Sector)。硬盘的第一个扇区,叫做引导扇区。扇区是被间隙(gap)分割的圆的片段,间隙未被磁化成0或者1。注意,扇区是读写磁盘最基本的单位,如果一个扇区因为某种原因被破坏,那么整个扇区的数据都会受影响。
根据上面的概念,不难得到硬盘容量的计算公式为:
硬盘容量(字节)=盘面数*每个盘面磁道数*每个磁道扇区数*每个扇区的字节数
另外,根据上面介绍的原理,每个盘面的磁道数也即柱面数;一般来说,每个扇区的字节数一般是512字节,所以可得:
硬盘容量(字节)=盘面数*柱面数*每个磁道扇区数*512字节
二 那如何管理磁盘中的数据呢?
下面,由浅入深的给出几个文件管理的模型,并分析其缺点,从而引出FAT32的核心思想。
模型一:文件名与文件直接存放在一起,存储时连续的占用所有的磁盘空间。这是最简单的存储模型。
但是,这种模型的缺点显而易见:
(1)效率低下: 当寻找一个文件时,需要从头读取扇区,在其中检测文件名,最坏的情况下,需要遍历整个磁盘。
(2)不便于进行增删改查:当扩充一个文件的大小时,要么移动后面所有的文件、要么放弃这块空间,把所有的数据转移到另一块更大的空间上去。
模型二:在模型一的基础上,把文件名放到扇区的开始处。
这种模型是否解决了模型一存在的问题呢?并没有。
以这种方式存储文件在模型一的基础上提高了一点搜索的效率,但是依旧需要逐个搜索扇区,提升有限。同样的,这种存储模型也会造成存储资源的浪费。
通过以上两个模型,不难看出,文件系统应该满足以下几个基本的需求:
1 给定一个文件名就能够快速找到相应的文件。
2 充分利用存储空间。
3 方便的进行增删改查。
那如何能够实现这些需求呢?
针对需求1,在前面我们的分析中,造成查找效率低下的主要原因是需要逐个搜索扇区来查找文件名,那怎样才能在逐个扇区查找呢? 我们可以在磁盘中开辟一块区域,专门用来记录文件名,以及该文件存放在磁盘中的位置,当需要查找文件时,我们在该区域搜索到文件存放的位置,直接去相应的位置读取数据就行了。
针对需求2,在前面我们的分析中,存储空间浪费是因为在上面两个模型中,文件都是连续存储的,一旦文件大小有所变化,存储空间大小不再合适就将其舍弃,这样就造成了空间浪费。那怎样才能充分利用碎片的存储空间,让文件可以不连续的存储呢?这里我们可以借用链表中的思想,我们在前一个扇区中记录下后一个扇区的地址,当前一个扇区的数据读取完成后,根据记录的地址就可以直接访问后一个扇区。
针对需求3,如果实现了需求2,需求3就迎刃而解了,我们只需要在增删改查程序时,记录下相应的地址变化即可。
分析至此,FAT32的思想已经跃然纸上了。