说明:该系类文章更多的是从从哲学视角看 操作系统 这门学科。同时也是 操作系统的学习笔记总结。因为博主 这些年主要是以研究安卓系统和 嵌入式Linux为主,因此这个系类文章也是这两个领域不可或缺的基石之一,尤其是对操作系统感兴趣的伙伴可特别关注。


17 文件系统实现

人们对事物的取向是基于对事物状态的判断;不同的判断自然导致不同的行为。,在文件实现上也一样,不同的看法和判断导致了文件实现的不同机制的出现。从用户角度看文件,是对文件系统的一种感性认识,但是对于设计者而言,这些知识是不够的,我们需要的是文件系统的实现细节。从设计者的角度看,他们关心的问题如图所示:

  • 文件系统是如何分布的。
  • 文件是怎么实现的。
  • 文件夹是怎么实现的。
  • 共享文件是怎么实现的。
  • 磁盘空间是如何管理的。

 一般对磁盘进行分区的原因:

  • 不同分区可以建立不同的文件系统。
  • 安全性上有优势:一个分区坏了不影响另一个分区。
  • 额可靠性上的优势:一个分区的故障不影响另一分区。
  • 但是最主要的是:据算计内存字长通常有限,磁盘地址需要放在内存字里面。使用分区可以使内存一次访问到更多的内容。

17.1 文件系统的布局

一个磁盘分解为一个个的扇面,编号从0递增,以整数计数。

@1 第0个扇面在整个文件系统中占有重要意义,因为 第0个扇面存放的是主引导记录(Master Boot Record,MBR)。记录的内容是一个用来启动计算机的小程序(如果该扇面损坏,则整个磁盘就无法使用),

@2 后面紧接着的是磁盘分区表。磁盘分区表里给出的是磁盘的所有分区及其开始地址和终结地址,其中一个分区为主分区。操作系统就装载在这个分区里。

@3 主分区里面最前面的是引导记录(Boot Record,BR)。在计算机启动时,处于主板ROM甲面的BIOS程序首先运行。BIOS在进行一些基本的系统配置扫描后对磁盘的扇面0进行读操作,将MBR里面的程序读到内存并运行。MBR程序接下来找到系统主分区,并将主分区里面的BR加载并运行。BR里是一个小程序,该程序将负责找到操作系统映像,并加载到内存.从而启动操作系统所有的文件系统都必须按照这种格式存放,操作系统才能正常启动。

@4 在BR记录块后面的内容就因情况而异,但是一般来说,在该记录块后面的磁盘内容布局因文件系统的不同而不同。但在通常情况下:

  • 紧接着引导记录后面的是一个超级数据块(super_Block,SB),该块里面存放的是关于该文件系统的各种参数。
  • 在SB后面则是磁盘的自由空间;
  • 其后面是i_node区;
  • 再后面是文件系统根日录区。
  • 分区的最后存放的是用户文件和文件夹区。

 文件系统的布局如图所示:

操作系统哲学原理(17)文件原理-文件系统实现_文件系统

 注意:对于FAT32文件系统,i_node区是不存在的。(在讨论具体的文件系统时,需要参阅具体的文件手册)

17.2 文件的实现

文件的实现,就是要能够把文件的内容存放在合适的地方,在需要时候很容易地读出这些数据。这样,文件的实现要解决的就是如下几个问题:

  • 给文件分配磁盘空间。
  • 记录这此磁盘空间的位置。
  • 将文件内容存放在这些空间。

数据在磁盘上的存放方式有下面两种:

  1. 连续空间存放
  2. 非连续空间存放分为两种方式:链表方式 和 索引方式。

17.2.1 连续空间的存放方式

一种属于常理,很容易被人们认同的方式,在这种模式下,一个文件数据占用连续的数据块(这种连续的块叫做盘区)

  • 连续存放的优点:读写效率很高,因为一次寻道就可以读出整个文件。
  • 连续存放的缺点:需要事先知道一个文件需要的空间大小、空间浪费(磁盘碎片)、文件不易扩展。

我们发现,实际上连续存放导致很多缺点,因此更换成另一种解决方案:非连续空间存储方式。

17.2.2 非连续空间的存放方式

非连续空间的存放方式:一个文件的数据块不需要在磁盘上占据连续的一片空间。使用链表可以找到文件所有的数据块,是一种解决办法。

链表的存放方式如下:

操作系统哲学原理(17)文件原理-文件系统实现_文件名_02

这种方式的优点:

  • 可以利用碎片

这种方式的缺点:

  • 访问速度慢,尤其是相对随即访问而言。
  • 可靠性低,如果一个指针损坏,则无法重构整个文件。
  • 增加了存储开销,因为指针要占用空间。

计算机对2的整数次方处理的很快,对于非2的整数次方的数据,处理效率急剧下降(因为指针要占用空间),那么如何克服这种存放方式的缺点呢:就是将指针全部抽出来形成一张表,要想知道一个数据块的位置,就查表,表放在内存里面。这种表就是文件分配表(File Allocation Table,FAT),如图所示:

操作系统哲学原理(17)文件原理-文件系统实现_文件系统_03

文件A的第一个数据块存放在物理磁盘块3上面:

  • FAT里面索引为3的记录里面存放的就是A的第2个数据块存放的物理磁盘块,A的第2个数据块存放在物理磁盘块10里;
  • FAT里索引为10的记录内容是18,说明A的第3个数据块存放在物理磁盘块18里;
  • FAT里索引为18的记录内容是13,说明文件A的下一个数据块在物理磁盘块13里;
  • FAT里索引为13的记录内容为6,说明下一个数据块在第6个物理数据块里;
  • FAT里索引为6 的记录内容是15,说明下一个数据块在第15个物理数据块里;
  • FAT里索引为15的记录内容为-1,说明该文件没有下一个数据块,即文件已经结束;

这样,根据FAT表,我们得出文件A所占的物理磁盘块顺序为:3-10-18-13-6-15;这样我们那只需要记住文件A的起始物理磁盘快为3即可。如果我们要随机读写文件,则仍然需要从第l个数据块地址开始,在FAT表里面顺着指针找到特定数据块所存放的物理磁盘块后才能读取该块数据。但这里的指针跟踪与使用链表时有着巨大的不同:这里的跟踪在内存发生,不是在磁盘上发生,因此效率大大提高。读写任何一个数据块均只需要一次磁盘访问。

注意:无论是文件分配表还是链表组织,只是形式不同而已,所有链接指针都集中存放,这和下面的索引文件组织是有本质的不同。

17.2.3 FAT32文件系统

  • 使用FAT机制的文件系统就称为FAT文件系统。而FAT文件系统又有FAT12、FAT16、FAT32三种。这三种的区别在于用来表示磁盘地址的内存字位数。如果用12位来表示磁盘地址,则是FAT12,用16位就是FAT16。不过FAT32却并不是使用32位内存字位来表示磁盘地址,而是28位。但因为28听上去不像32那样像2的指数次方,所以就叫它FAT32。FAT的共种文件系统在Windows上均获得了广泛的应用。
  • 那么FAT表是否占用大量的内存空间得看磁盘有多大。FAT表的大小与物理磁盘大小和磁盘数据块大小有关。由于FAT表的记录项与物理磁盘块数一样,磁盘越大,磁盘数据块越小,FAT表越大。(页表很大是一个大问题,这里FAT表很大也是一个大问题。当然,我们可以采取分页系统里采取的办法,只将FAT表的一部分存放在物理内存,其他存放在磁盘上来减轻这个问题。但这种解决方案的代价则有可能造成文件访问效率的降低。因此一个改进的方法就是就是索引文件组织)

17.2.4 索引文件组织

经过研究发现,FAT很大,但是里面存放的信息不一定很多;如果文件很多且尺寸较小,则FAT里很多记录是空的。这样讲整个FAT放在内存里就有些不必要了。如果能够将每个文件的所有数据块的磁盘地址收集起来,集中放在一个索引数据块,而在文件打开时将该数据块加载到内存,那么以后访问任何一个数据块都可以从该索引数据块里面获得物理磁盘地址。这样,内存里面存放的只是我们需要使用的文件的数据块的所有地址.而不是各种不相干的文件的地址全部一次加载到内存。这样,FAT占用内存太多的问题就解决了。这种索引数据块就称为I_NODE,这里的I即是索引(Index)一词的缩写。但是由于I_NODE里面寻访的不仅是文件地址索引,还有其他关于文件的信息(文件属性等),如图所示:

操作系统哲学原理(17)文件原理-文件系统实现_文件系统_04

如果要访问一个文件,则首先将其对应的I_NODE打开。根据I_NODE的内容,可以找到任何想要访问的数据块。I_NODE非常类似于页表的管理。页表存放的是虚拟页面到物理页面的对应,而文件头存放的是逻辑数据块到物理数据块的对应。索引块与页表相似,页表除了存放地址映射外,还存放别的信息。索引块也可以在地址对应之外存放了别的信息(这些信息包括文件创立时间、修改时间、是否为系统文件等)。

索引文件由于也属于非连续组织方式,自然继承了链表和FAT方式的优点。索引组织的缺点也与FAT方式类似:比较麻烦。因为每个数据块都需要进行选点,相当于一系列随即访问,即顺序访问效率不太高。虽然文件增长灵活,但如果一次文件大小的增长超过了预期,其需要的数据块数超过索引头预留的指针一数时不好办(例如,如果只分配了50个指针,文件尺寸在一定字节范围内时增长很容易;但如果超过这个范围就不容易增长了。虽然可以重新分配一个更大的I_NODE.将原来文件头里面的数据复制到新的文件头,然后再分配新的磁盘空间,更新文件头。不过这种做法有两个问题:

  1. 需要进行数据的移动,浪费时间;
  2. 使得文件头大小可以任意变化,而这将令文件系统的管理变得复杂。)

从而需要较好的解决办法:使用多级索引文件组织结构。

17.2.5 多级索引文件组织

在分页系统里面.页表太大时我们使用多级页表。当然可以在文件太大时使用多级索引头,即使用间接I_NODE,多级I_NODE如图所示:

操作系统哲学原理(17)文件原理-文件系统实现_多级_05

不过,这种多级索引组织有一个缺点.就是访问数据块所需要的磁盘访问次数增加。因为访问次级I_NODE需要一次磁盘访问,因此磁盘访问速度很低。这种次数的增加显然不好。另外,多级索引还有一个缺点,就是对于小文件来说,它们使用的磁盘数据块可能不会超过一个I_NODE里面的指针数。但由于使用多级索引,就白自浪费了I_NODE空间。这个问题得解决方案就是非对称多级索引。

17.2.6 非对称索引文件组织

既然单级索引不能适用于大文件,而多级索引又不适用于小文件,那能想到的一种办法自然是单级和多级的有机组合:非对称多级索引。在对称多级索引组织下,索引既可以是单级,也可以是多级。到底是单级还是多级取决于文件的大小。所有的文件都有一个顶级索引节点(I_NODE)。不过这里比较特别的是I_NODE里面的指针域被分为两个部分:一部分用来存放数据块所在的磁盘地址,一部分用来存放次级I_NODE的地址。这样,如果文件尺寸较小,其所占数据块数没有超过I_NODE里面分配的数据块指针数,则其数据块磁盘地址全部存放在顶级I_NODE上。这样的文件将没有次级索引。如果文件较大.则除了顶级数据块磁盘地址外.还将有次级I_NODE,如图所示:

操作系统哲学原理(17)文件原理-文件系统实现_数据块_06

  • 如果一个I_NODE里而可以存放50个指针,50个指针不是全部用来存储数据块对应的磁盘块地址,而是留两个指向磁盘块,称为间接磁盘块。而间接磁盘块上存放的则是数据磁盘块的地址。I_NODE里面指向数据块的指针称为直接指针,指向间接磁盘块的指针称为间接指针。
  • 非对称索引具备了单级索引和多级索引的优点,因为这里还涉及到了心理学相关的东西(先将前面的数据块呈献给用户,在用户看的过程中将后面的数据块再加载)
  • 如果一级间接还不能容纳系统里的大文件,那就可以使用二级间接、三级间接、当然,随着间接层次的增加,文件的访问速度将随着下降,最后可能达到不能容忍的地步。因此,在实际的商业操作系统里,间接的次数都有个上限(UNIX的V7文件系统的间接层数为3),一旦间接层数设定,则一个文件系统里能够存放的文件最大尺寸也就确定了。

17.2.7 文件缓存

无论是单级还是多级,文件的读取相对内存来讲还是慢,对于慢的解决办法就是:使用缓存(将文件里经常要访问的内容放在缓存里,使得文件的访问可以再缓存满足,而无需到磁盘上读写,这种缓存称为文件缓存)

17.3 目录实现:地址独立的实现

文件夹的任务是提供从文件名到文件的地址映射.对不同的文件组织形式,文件的地址表示也不一样。几种存放形式如下:

  • 连续存放形式:只需要文件的第一个数据块的磁盘地址即可,后面的数据块紧接在该数据块后面。这种情况下文件夹里面存放的映射是到文件头数据块地址。
  • 链表组织形式:只需要文件的第一个数据块磁盘地址即可,后面的数据块可以通过前面数据块里面的指针获得。这种情况下文件夹里而存放的映射也是到文件头数据块地址。
  • FAT组织形式:映射仍然保持不变,可以从FAT表里面找到后继数据块所在的物理磁盘地址。
  • I_NODE组织形式:只需要知道文件对应的顶级I_NODE地址即可。文件的数据块地址可以从I_NODE里面获得。文件夹里面存放的映射是到I_NODE的编号。

17.3.1 文件属性的存放

文件属性的存放根据文件组织方式的不同而不同。

  • 如果是连续/链表的组织形式,则只有文件夹里可以存放文件属性。
  • 如果是I_NODE组织形式,则属性既可以存放在文件夹里,也可以存放在I_NODE表里。

将文件存放在文件夹里和I_NODE表里的模式如图:

操作系统哲学原理(17)文件原理-文件系统实现_数据块_07

17.3.2 长文件名的存放

文件夹存放从文件名到文件地址的映射。一个文件将在文件夹里面占用一个记录。记录总会有一个长度。为了便于文件的读取,文件夹里面的记录长度通常是固定的。那么对于文件名很长的情况,即文件名长度超过记录能容纳的长度时,我们存放文件名的方法:

  • 最简单的办法是不允许长文件名。但这个办法很可能会激怒用户。
  • 在文件夹里给长文件名的文件分配多个记录空间,用以存放长文件名。(这样将造成每个文件占用文件夹记录数不一样的情况。而这将使得文件的读写操作复杂性增加)但这种方式要求在查找文件时顺序扫描文件夹,并动态计算下一个文件开始的位置,因此,效率十分低下。可变长度文件记录的存放方式如图所示:

操作系统哲学原理(17)文件原理-文件系统实现_链表_08

除此之外,还有一个办法是将文件名存放在另一个分开的地方(如系统堆空间),这样每一个文件记录里面保存一个指针指向堆里存放该文件名的地址。此种情况下,由于文件记录保持不变,在扫描文件夹时无需动态记录下一个文件开始的位置,效率将提高。如下所示:

操作系统哲学原理(17)文件原理-文件系统实现_链表_09

17.3.3 文件共享

符号链接可以让多个用户共享一个文件,具体实现如下:一个文件可以从多个路径访问,即从多个路径都可以找到文件在磁盘上存放的地址,该文件的映射保存在多个文件夹里。为了保持系统的一致性,此时在文件的I_NODE里面记录其被链接的次数。一个从文件夹4链接文件5的情况如图所示:

操作系统哲学原理(17)文件原理-文件系统实现_数据块_10

有了链接后,文件删除的操作需要进行修改。删除文件时不是马上将文件侧除(不管是逻辑上还是物理上),而是将该文件对应I_NOOE里面的链接计数-1。

  • 如果结果为0,就删除该文件(逻辑删除)
  • 如果不为0,则不删除该文件。(这是因为还有目录需要使用该文件;如果这时删除了,将出现魅影,即一个文件在目录夹里面显示,但实际却不存在)

17.3.4 硬链接

将文件的地址映射直接加到链接目录下,这种链接也称为硬链接。这是因为其中一条路径断开后(如删除文件或者路径下的文件夹),其他的链接不会受到影响。但这种链接的缺点:

  • 文件所有者的文件的操控能力变小,因为仅限于自己的链接。
  • 使得文件的创建者没有权利断开用户的链接。

我们需要向办法既即可以提供链接,又赋予文件创仅者更多的控制,这种方式就是软链接。

17.3.5 软链接

要想将链接变软,就不能将文件的地址直接存放在链接目录里。而不存放文件的磁盘地址还可以访问到该文件的方法当然是间接了。就是在链接目录里存放到链接文件的原始路径名(文件被创立时使用的路径名)。即从链接目录访问文件需要走原始路径过来。这样当原始路径断开时,该链接就自然也断开了。这种在原始路径断开后不能维持的链接就称为软链接。软链接从严格意义上不是链接,因为并没有直接链接到文件,而是保存了文件的原始访问路径。windows的快捷方式不是链接。因为快捷方式保存的就是路径名。不用硬链接原因:Windows上经常使用FAT文件系统,没有地方存放文件的链接计数,硬链接无法实现。当然,如果是NTFS,则可以使用链接。但为保险起见,还是不用为妙。

17.3.6 切断链接

切断链接就是将目录夹里面相应的文件记录删除:对于软链接来说,就是将存放原始访问路径的文件删除。链接切断后,在目录里面将看不到原来被链接的文件。

17.3.7 链接带来的问题

链接方便共享,但是也存在很多问题。最主要的就是文件备份困难,在进行逻辑备份时,如果选择备份的文件夹里存在符号链接,则从逻辑上看,该文件存在多个路径;这样将造成文件备份多次(备份时不过是浪费了一点空间);但是恢复的时候由于被链接的文件备份了多个拷贝,自然也就恢复了多个拷贝。这样就达不到共享的目的了(每个路径有自己的拷贝,这是操作的不是共享文件,而是各自的备份文件了);如果对软件备份进行修改,使其辨认出符号链接,则代价太大。

17.3.8 文件系统挂载

挂载:将一个文件系统并到另一个文件系统的方法。挂载需要提供被挂载文件系统的根目录和挂载点,而挂载就是修改挂载点的目录内容,增加一个记录将文件系统的根目录I_NODE地址保存起来,文件系统的挂载情形如下:

操作系统哲学原理(17)文件原理-文件系统实现_链表_11

在windows操作系统下,挂载点一般是“我的电脑”,这是windows文件系统的根目录。但在新的Windows版本下,也可以挂载在非根目录下。在UNIX/Linux下挂载点可以是任何目录。

17.3.9 卸载

挂上去的文件也可以卸下来,称为卸载。卸载即是将挂载点的目录内容中的相关记录删除。对于光盘来说,弹出光盘就是卸载光盘文件系统;对于U盘来说,拔出就是卸载。

17.4 闲置空间管理

文件系统对闲置空间的管理与内存空间管理一样,也是位图和链表。

17.4.1 磁盘分配块

文件系统分配空间是按照块(block)来分配的,Windows将这种分配块称为簇,块/簇的尺寸在超级数据块中记录着。有了这个参数,就可以把字节数转换成块/簇。磁盘块应该分多大,应该根据实际情况折中,即使一个系统里面文件的平均大小。

  • 如果尺寸大了:浪费空间多
  • 如果尺寸小了;数据传输速度慢

分配块的大小应该与文件的平均尺寸存在某种联系。磁盘分配块和磁盘利用率以及有效磁盘数据传输之间的关系如下:

操作系统哲学原理(17)文件原理-文件系统实现_文件名_12

17.4.2 磁盘配额

文件系统给每个用户一个磁盘配额。可以用空间表示,也可以用文件数表示,更为常见的是两者同时使用(一个用户只能创建一定数量的文件,且空间不能超过某个上限值)。

对容量配额的实现,不同的操作系统使用的方法也不一样,在UNIX环境下,磁盘配额分为两类:

  • 软配额:可以临时超过,但是必须在下次登录前解决这个问题。
  • 硬配额:不可以超过,超过即超出配额的文件将被删除(具体实现要看操作系统)。