🌈 个人主页:十二月的猫-CSDN博客
🔥 系列专栏: 🏀操作系统与数据库_十二月的猫的博客-CSDN博客💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光
目录
1. 前言
【操作系统】系列以后将只做此类型的文章,方便初学者/回顾者来学习/复习操作系统底层的知识。该类型一篇回顾一个知识点,力求将该知识点按照初学者的角度和层次讲透讲完整,而非囫囵吞枣、走马观花。
如果您想要浅浅了解该知识,可以换一篇文章哦🫡。因为一旦打开我的文章,你将真正打开操作系统的大门📍
2. 计算机与文件系统
学习一个事物,首先要明白为什么我们学习的目的是什么?🫠🫠
所以,我就想问,文件系统有什么用呢,它在我们的计算机中承担什么样的地位。
我相信弄清楚文件系统的“帝位”后,你将感叹其关键与玄妙从而迫切想要学习文件系统。
我们知道:
所有的应用程序都需要存储
和检索
信息,任何应用程序的运行都需要一个空间去存储它产生的临时变量信息,同时也可能需要它过去产生的信息参与到现在的活动当中。
- 存储运行产生的临时变量。
- 过去活动产生的变量。
因此一个用来存储信息的空间是必须的。我们的操作系统自然也会有内存分配给进程,进程运行时,它能够在自己的存储空间内存储一定量的信息。但是这个空间存在一定的问题,不能很好的满足上面两个要求:
- 存储容量受
虚拟地址空间
大小的限制(进程运行时,CPU会分配一部分空间给他,这个空间是虚拟的内存空间,不是程序员眼中连续实际的内存空间)。对于一些应用程序来说,存储空间的大小是充足的,但是对于其他一些应用程序,比如航空订票系统、银行系统、企业记账系统来说,这些容量又显得太小了。 - 当进程终止时信息会丢失。对于一些应用程序(例如数据库),信息会长久保留。在这些进程终止时,相关的信息应该保留下来,是不能丢失的。甚至这些应用程序崩溃后,信息也应该保留下来。
- 过去活动产生的变量可能同时被多个进程访问使用,但是上面提到的分配给每一个进程的空间是保留再各自进程中的,彼此访问相当复杂。
所以,仅仅依靠进程本身的虚拟内存空间是远远不够的。我们就需要另外一个片空间,这个空间需要满足以下要求:
- 能够存储大量临时产生的信息
- 能够持久性保存部分信息
- 允许多个进程同时访问
- 不一定需要快速访问,当然越快越好
进程被分配得到的虚拟内存空间都是CPU内部的寄存器,造价非常昂贵,而上面提到的另外一个空间需要的能够存储大量临时产生的信息。
因此我们经常使用另一套存储设备,而不是寄存器,这个设备就是磁盘。不过近些年来,
固态硬盘
逐渐流行起来,但是作为大容量的首选——磁盘,仍然目前在大容量存储领域还有很大的市场空间,因此下面我们将针对磁盘展开。
固态硬盘有SATA、PCIE、M.2接口(上图是SATA口的固态硬盘)
磁盘:
磁盘可以姑且认为是一种大小固定块的线性序列,将磁盘分为:
- 读块 k
- 写块 k
因为磁盘容量大,并且有读写操作,原则上就能够解决长期存储、容量不够的问题。
但是我们马上就有其他的问题:
- 如何找到这些信息?
- 如何支持多进程访问,而不会冲突?
- 写入信息时怎么确定写在哪一块上(哪一块是空的)
- 等等
想要解决上面的问题,就要引入我们的新概念——文件系统✨✨
文件系统顾名思义就是对文件进行统一管理的系统,所以我们先来看看文件是什么?
3. 文件
3.1 文件命名
文件是一种抽象机制,它提供了一种方式用来存储信息以及在后面进行读取(类似于集合概念:将一些数放在一起,方便一起进行数学操作;文件是将一些信息以二进制数的形式放在一起,方便后续的查找与使用)。为了方便后续的查找与使用,我们要为每一个文件命名,之后我们可以使用文件名字来访问文件。
3.1.1 不同操作系统的文件命名
文件命名规则对于不同的操作系统来说是不一样的。例如某些文件区分大小写字母,而大多数则不区分。UNIX 属于第一类;历史悠久的 MS-DOS 属于第二类(顺便说一句,尽管 MS-DOS 历史悠久,但 MS-DOS 仍在嵌入式系统中非常广泛地使用,因此它绝不是过时的);因此,UNIX 系统会有三种不同的命名文件:maria、Maria、MARIA 。在 MS-DOS ,所有这些命名都属于相同的文件。
Windows 95 和 Windows 98 使用了 MS-DOS 文件系统,改名叫做:FAT-16,因此继承了MS-DOS 的一些基本特性,其中包括文件名的命名规则和文件存储结构等。FAT-16 是一种相对较简单的文件系统,广泛应用于早期的 Windows 操作系统中。在 Windows 98 中,微软对 FAT-16 进行了扩展,支持了更大的磁盘分区和文件存储,从而诞生了 FAT-32。虽然 FAT-32 是对 FAT-16 的一种改进,但两者在很多方面仍然相似,主要的区别在于文件系统的容量和管理方式的改进。
后面的Windows 操作系统如 Windows NT、Windows 2000、Windows XP、Windows Vista、Windows 7 和 Windows 8 也都引入了更为先进的本机文件系统——NTFS(New Technology File System)。NTFS 提供了许多比 FAT 更强大的功能,包括对大容量磁盘的支持、更强的文件安全性、日志记录、压缩等,并且支持基于 Unicode 编码的文件名,这使得文件名可以包含多种语言的字符。当然,这些Windows操作系统也都支持 FAT 文件系统。尽管 FAT 文件系统已经相对过时,但它仍然在一些应用场景中得到了保留。
除了 NTFS,Windows 8 还引入了一种新型的文件系统——ReFS(Resilient File System,弹性文件系统)。ReFS 主要用于服务器版本的 Windows 8,它具有更强的数据完整性保护和容错能力,适合用于高可靠性和高可用性的存储环境。
值得注意的是,虽然 Windows 系统广泛支持 FAT 系列文件系统(FAT-16 和 FAT-32等等),我们通常所指的 FAT 文件系统就是 Windows 中的这两种格式。如果没有特别说明,"FAT 文件系统" 一般是指 FAT-16 或 FAT-32。
另外,还有一种与 FAT 类似的现代文件系统——exFAT(Extended FAT)。exFAT 是微软为闪存驱动器和大文件系统开发的一种优化版本,旨在克服 FAT-32 在大文件和大容量存储设备上的一些限制。exFAT 支持更大的文件和更高效的存储管理,尤其适用于 SD 卡、USB 驱动器等存储介质。值得一提的是,exFAT 是微软唯一能够与 macOS 操作系统兼容的文件系统,支持 OS X 系统的读写操作。
3.1.2 文件命名的基本规则
大部分操作系统支持两部分的文件名,它们之间用 . 分隔开,比如文件名 prog.c。原点后面的文件称为 文件扩展名(file extension) ,文件扩展名通常表示文件的一些信息。例如在 MS-DOS 中,文件名是 1 - 8 个字符,加上 1 - 3 个字符的可选扩展名组成。
在 UNIX 中,如果有扩展名,那么扩展名的长度将由用户来决定,一个文件甚至可以包括两个或更多的扩展名,例如 homepage.html.zip,html 表示一个 web 网页而 .zip 表示文件homepage.html 已经采用 zip 程序压缩完成。一些常用的文件扩展名以及含义如下图所示:
UNIX系统中:
例如:名为 file.txt
的文件是文本文件,这个文件名更多的是提醒所有者,而不是给计算机传递信息。换句话说,文件名(文件名字+拓展名字)对于操作系统(文件系统)来说是透明的。
所有者在这里不仅仅指用户,也指使用这些文本文件的程序/应用。例如 C 编译器可以编译、链接多种文件,包括 C 文件和汇编语言文件。这时扩展名就很有必要,编译器利用它们区分哪些是 C 文件,哪些是汇编文件,哪些是其他文件。因此,扩展名对于编译器判断哪些是 C 文件,哪些是汇编文件以及哪些是其他文件变得至关重要。
Windows系统中:
Windows 系统会关注扩展名。用户(或进程) 可以在操作系统中注册扩展名,并且规定自己可以使用的文件拓展名有哪些。当用户双击某个文件名时,拥有该文件名的程序就启动并运行文件。例如,双击 file.docx 启动了 Word 程序,并以 file.docx 作为初始文件。
4. 目录
文件系统为了更好的组织安排文件,设计了目录这个功能。
文件系统通常提供目录(directories)
或者 文件夹(folders)
用于记录文件的位置,在很多系统中目录本身也是文件,下面我们会讨论关于文件,他们的组织形式、属性和可以对文件进行的操作。
4.1 一级目录
目录系统最简单的形式是有一个能够包含所有文件的目录。这种目录被称为根目录(root directory)
,由于根目录的唯一性,所以其名称并不重要。在最早期的个人计算机中,这种系统很常见,部分原因是因为只有一个用户。下面是一个单层目录系统的例子
该目录中有四个文件。这种设计的优点在于简单,并且能够快速定位文件,毕竟只有一个地方可以检索。
4.2 多层次目录
对于简单的应用而言,一般都用单层目录方式,但是这种组织形式并不适合于现代计算机,因为现代计算机含有成千上万个文件和文件夹。如果都放在根目录下,查找起来会非常困难。为了解决这一问题,出现了层次目录系统(Hierarchical Directory Systems),也称为目录树。通过这种方式,可以用很多目录把文件进行分组。进而,如果多个用户共享同一个文件服务器,比如公司的网络系统,每个用户可以为自己的目录树拥有自己的私人根目录。这种方式的组织结构如下
根目录含有目录 a、b ,分别属于不同的用户,其中a用户创建了两个子目录c和d
。用户可以创建任意数量的子目录,现代文件系统都是按照这种方式组织的。
5. 文件系统
文件系统就是对文件组织管理的一个系统,想要对文件进行组织管理就需要在磁盘中存储文件原本的data以外,再加入控制信息,例如文件大小、文件目录、文件所属者等。这些信息都是文件系统组织管理文件所必要的信息。
因此研究文件系统首先就要来研究文件系统下这些文件在磁盘中的完整信息。
磁盘与文件系统的关系:
磁盘是物理存储介质,而文件系统是组织和管理磁盘上数据存储的逻辑结构,负责如何在磁盘上存储、访问、管理和保护文件。
之前大家关心的一直都是文件是怎样命名的、可以进行哪些操作、目录树是什么,如何找到正确的文件路径等问题。而设计人员关心的是文件和目录是怎样存储的、磁盘空间是如何管理的、如何使文件系统得以流畅运行的问题,下面我们就来一起讨论一下这些问题。
文件系统管理下的磁盘以及磁盘文件主要结构包括:MBR、引导块、超级块、空闲空间管理、inode、根目录、文件和目录。
下面我们来一一讲解✨✨
5.1 MBR与引导块
广义上的引导块包括:
- 每个磁盘分区的引导块
- 整个磁盘的引导块MBR
狭义上的引导块包括:
- 每个磁盘分区的引导块
MBR和磁盘分区的引导块作用是存在不同的:
- MBR中有引导程序,会在计算机启动时启动,引导计算机跳转到操作系统所在磁盘分区,让该磁盘分区的引导块去完成接下去的操作。(如果是操作系统所在的磁盘分区,则引导块将去加载操作系统;如果不是操作系统所在的磁盘分区,则引导快将负责其他的活动)
- MBR包含一个分区表,用来查看整个磁盘中各个分区的位置和大小等信息。
- 磁盘分区内的引导块,如果分区内有操作系统则其要在MBR引导到该分区准备启动操作系统时,完成操作系统的加载。如果没有操作系统,则处理其他活动或者不做任何处理
MBR 做的第一件事就是确定活动分区(根据分区表确定)(活动分区就是操作系统所在的分区),读入它的第一个块,称为引导块(boot block) 并执行。引导块中的程序将加载分区中的操作系统。为了一致性,每个分区都会从引导块开始,即使引导块不包含操作系统。引导块占据文件系统的前 4096 个字节,从磁盘上的字节偏移量 0 开始。引导块可用于启动操作系统。
在计算机中,引导就是启动计算机的过程,它可以通过硬件(例如按下电源按钮)或者软件命令的方式来启动。开机后,电脑的 CPU 还不能执行指令,因为此时没有软件在主存中,所以一些软件必须先被加载到内存中,然后才能让 CPU 开始执行。也就是计算机开机后,首先会进行软件的装载过程。
重启电脑的过程称为重新引导(rebooting),从休眠或睡眠状态返回计算机的过程不涉及启动。
5.2 超级块
超级块(Superblock)是文件系统中存储重要元数据的区域,记录了文件系统的整体结构信息,如大小、状态、可用空间、文件系统类型等。
紧跟在引导块后面的是 超级块(Superblock)
,超级块 的大小为 4096 字节,从磁盘上的字节偏移 4096 开始。超级块包含文件系统的所有关键参数
- 文件系统的大小
- 文件系统中的数据块数
- 指示文件系统状态的标志
- 分配组大小
在计算机启动或者文件系统首次使用时,超级块会被读入内存。
5.3 空闲空间块
空闲块用于记录文件系统中未被分配给文件的数据块,以便系统可以高效地分配存储空间给新文件或扩展现有文件。
主要方法有:
- 位图
- 指针列表
5.3.1 位图
位图或位向量是一系列位或位的集合,其中每个位对应一个磁盘块,该位可以采用两个值:0和1,0表示已分配该块,而1表示一个空闲块。下图中的磁盘上给定的磁盘块实例(分配了绿色块)可以用16位的位图表示为:0000111000000110。
5.3.2 指针列表(链表)
在这种方法中,空闲磁盘块链接在一起,即一个空闲块包含指向下一个空闲块的指针。第一个磁盘块的块号存储在磁盘上的单独位置,也缓存在内存中。
5.4 inode
inode(索引节点)存储文件的元数据,如文件的权限、所有者、大小、创建时间和数据块位置,但不存储文件名。
然后在后面是一个 inode(index node)
,也称作索引节点。它是一个数组的结构,每个文件有一个 inode,inode 非常重要,它说明了文件的方方面面。每个索引节点都存储对象数据的属性和磁盘块位置。
inode 节点主要包括了以下信息:
- 模式/权限(保护)
- 所有者 ID
- 组 ID
- 文件大小
- 文件的硬链接数
- 上次访问时间
- 最后修改时间
- inode 上次修改时间
文件分为两部分,索引节点和块。一旦创建后,每种类型的块数是固定的。你不能增加分区上 inode 的数量,也不能增加磁盘块的数量。
紧跟在 inode 后面的是根目录,它存放的是文件系统目录树的根部。最后,磁盘的其他部分存放了其他所有的目录和文件。
5.5 文件和目录
下面是文件系统文件和目录的总体架构图:
注意:两级目录项、和目录项所指向的头文件、头文件指向的文件数据处本质都是存储在一整个磁盘内部🚵♂️🚵♂️
6. 文件系统如何组织管理磁盘块(文件和目录的分配处理)
最重要的问题是记录各个文件分别用到了哪些磁盘块。不同的系统采用了不同的方法。下面我们会探讨一下这些方式。分配背后的主要思想是有效利用文件空间
和快速访问文件
,主要有三种分配方案:
- 连续分配
- 链表分配
- 索引分配
6.1 连续分配
磁盘直接访问的特点在文件实现时提供了灵活性。在几乎每种情况下,很多文件都是存储在同一个磁盘上的。主要的问题是,如何为这些文件分配空间,以便有效使用磁盘空间和快速访问文件。
磁盘空间分配的主要常用方法有三个:连续分配、链接分配和索引分配。每个方法各有优缺点。虽然有些系统对这三种方法都支持。但是更为常见的是,一个系统只对同一文件系统类型的所有文件采用一种方法。
连续分配方法要求,每个文件在磁盘上占有一组连续的块。磁盘地址为磁盘定义了一个线性排序。有了这个排序,假设只有一个作业正在访问磁盘,在块 b 之后访问块 b+1 通常不需要移动磁头。当需要磁头移动(从一个柱面的最后扇区到下一个柱面的第一扇区)时,只需要移动一个磁道。因此,用于访问连续分配文件的所需寻道数量最小,在确实需要寻道时所需的寻道时间也最小。
文件的连续分配可以用首块的磁盘地址和连续的块数来定义。如果文件有 n 块长并从位置 b 开始,则该文件将占有块 b,b+1,b+2,…,b+n-1。每个文件的目录条目包括起始块的地址和该文件所分配区域的长度,参见图 1。
图1 磁盘空间的连续分配
连续分配文件的访问非常容易。对于顺序访问,文件系统会记住上次引用的块的磁盘地址,如需要可读入下一块。对于直接访问一个文件的从块 b 开始的第 i 块,可以直接访问块 b+i。因此,连续分配支持顺序访问和直接访问。
不过,连续分配也有一些问题。一个难题是,为新文件找到空间。用于管理空闲空间的系统决定了这个任务如何完成,虽然可以使用任何管理系统,但是有的系统会比其他的要慢。
连续分配问题可以作为通用动态存储分配问题的一个具体应用,即如何从一个空闲块列表中寻找一个满足大小为 n 的空间。从一组空闲块中寻找一个空闲块的最为常用的策略是,首次适合和最优适合。模拟结果显示在时间和空间使用方面,首次适合和最优适合都要比最坏适合更为高效。首次适合和最优适合在空间使用方面不相上下,但是首次适合一般更快。
所有这些算法都有外部碎片的问题。随着文件的分配和删除,可用磁盘空间被分成许多小片。只要空闲空间分成小片,就会存在外部碎片。当最大连续片不能满足需求时就有问题;存储空间分成了许多小片,其中没有一个足够大以存储数据。因磁盘存储总量和文件平均大小的不同,外部碎片可能是个小问题,但也可能是个大问题。
为了防止外部碎片引起的大量磁盘空间的浪费,将整个文件系统复制到另一个磁盘。原来的磁盘完全变成空的,从而创建了一个大的连续空闲空间。然后,通过从这个大的连续空闲空间采用连续分配方法,将这些文件复制回来。这种方案将所有空闲空间有效合并起来,解决了碎片问题。
这种合并的代价是时间,而且大硬盘的代价可能特别高。合并这些磁盘空间可能需要数小时,可能每周都需进行。有些系统要求,这个功能线下执行且文件系统要卸载。在这停机期间不能进行正常操作,因此生产系统应尽可能地避免合并。大多数的需要整理碎片的现代系统能够和正常的系统操作一起在线执行合并,但是性能下降可能很明显。
连续分配的另一个问题是,确定一个文件需要多少空间。当创建一个文件时,需要找到并分配它所需空间的总数。创建者(程序或人员)又如何知道所创建文件的大小?在某些情况下,这种判断可能相当简单(例如,复制一个现有文件),一般来说,输出文件的大小可能难以估计。
如果为文件分配的空间太小,则可能会发现文件无法扩展。特别是对于最优适合的分配策略,文件两侧的空间可能已经使用。因此,不能在原地让文件更大。
这时,有两种可能办法:
终止用户程序,并给出适当的错误消息。 这样,用户必须分配更多的空间,并再次运行该程序。这些重复的运行可能代价很高。为了防止这些问题,用户通常会高估所需的磁盘空间,从而造成相当大的空间浪费。
找一个更大的空间,将文件内容复制到新空间,并释放以前的空间。只要空间存在,就可以重复这些动作,不过如此可能耗时。然而,用户无需获知究竟发生了什么事情;而系统虽有问题仍继续运行,只不过会越来越慢。
即使文件所需的空间总量事先已知,预先分配仍可能很低效。一个文件在很长时间内增长缓慢(数月或数年),仍必须按它的最终大小来分配足够空间,即使这个空间很长时间内不用。因此,该文件有一个很大的内部碎片。
为了最小化这些缺点,有些操作系统使用连续分配的修正方案。这里,最初分配一块连续空间。以后,当这个数量不够时,会添加另一块连续空间(称为扩展)。然后,文件块的位置就记录为:地址、块数、下一扩展的首块的指针。
在有些系统上,文件所有者可以设置扩展大小,但是如果所有者不正确,这种设置会导致低效。如果扩展太大,内部碎片可能仍然是个问题;随着不同大小的扩展的分配和删除,外部碎片可能也是个问题。商用 Veritas 文件系统使用扩展来优化性能。Veritas 是标准 UNIX UFS 的高性能替代。
链接分配
链接分配解决了连续分配的所有问题。采用链接分配,每个文件是磁盘块的链表;磁盘块可能会散布在磁盘的任何地方。目录包括文件第一块和最后一块的指针。例如,一个有5块的文件可能从块 9 开始,然而是块 16、块 1、块 10,最后是块 25(图 2)。每块都有下一块的一个指针。用户不能使用这些指针。因此,如果每块有 512 字节,并且磁盘地址(指针)需要 4 字节,则用户可以使用 508 字节。
图 2 磁盘空间的链接分配
要创建一个新文件,只需在目录中增加一个新的条目。采用链接分配,每个目录条目都有文件首个磁盘块的一个指针。这个指针初始化为 null,表示一个空的文件。大小字段也设置为 0。写文件导致空闲空间管理系统找到一个空闲块,这个新块会被写入,并链接到文件的尾部。读文件,只需按照块到块的指针来读块。
采用链接分配没有外部碎片,空闲空间列表的任何块可以用于满足请求。当创建文件时,并不需要说明文件的大小只,要有可用的空闲块,文件就可以继续增长。因此,无需合并磁盘空间。
然而,链接分配确实有缺点。主要问题是,它只能有效用于顺序访问文件。要找到文件的第 i 个块,必须从文件的开始起,跟着指针,找到第 i 块。每个指针的访问都需要一个磁盘读,有时需要磁盘寻道。因此,链接分配不能有效支持文件的直接访问。
另一个缺点是指针所需的空间。如果指针需要使用 512 字节块的 4 字节,则 0.78% 的磁盘空间会用于指针,而不是其他信息。每个文件需要比原来稍多的空间。
这个问题的通常解决方案是,将多个块组成簇,并按簇而不是按块来分配。例如,文件系统可以定义一个簇为 4 块,在磁盘上仅以簇为单位来操作。这样,指针所占的磁盘空间的百分比就要小得多。这种方法使得逻辑到物理块的映射仍然简单,但提高了磁盘吞吐量(因为需要更少的磁头移动),并且降低了块分配和空闲列表管理所需的空间。这种方法的代价增加了内部碎片;如果一个簇而不是块没有完全使用,则会浪费更多空间。簇可以改善许多算法的磁盘访问时间,因此用于大多数操作系统。
链接分配的另一个问题是可靠性。回想一下,文件是通过散布在磁盘上的指针链接起来的,操作系统软件错误或磁盘硬件故障可能导致获得一个错误指针,这个错误可能会导致链接到空闲空间列表或链接到另一个文件。一个不完全的解决方案是,采用双向链表;另一个是,每块存储文件名称和相对块号。然而,这些方案为每个文件增加了更多额外开销。
链接分配的一个重要变种是文件分配表(FAT)的使用。这个简单而有效的磁盘空间分配方法用于 MS-DOS 操作系统。每个卷的开头部分的磁盘用于存储该表。在该表中,每个磁盘块都有一个条目,并可按块号来索引。FAT 的使用与链表相同。目录条目包含文件首块的块号。通过这个块号索引的表条目包含文件的下一块的块号。这条链会继续下去,直到最后一块;而最后一块的表条目的值为文件结束值。未使用的块用 0 作为表条目的值来表示。为文件分配一个新块只要简单找到第一个值为 0 的 FAT 条目,用新块的地址替换前面文件结束值,用文件结束值替代 0。由块 217、618、339 组成的文件的 FAT 结构如图 3 所示。
图 3 文件分配表
如果不对 FAT 采用缓存,FAT 分配方案可能导致大量的磁头寻道时间。磁头必须移到卷的开头,读入 FAT,找到所需块的位置,再移到块本身的位置。在最坏的情况下,每块都需要移动两次。优点是改善了随机访问时间;因为通过读入 FAT 信息,磁头能找到任何块的位置。
索引分配
链接分配解决了连续分配的外部碎片和大小声明的问题。然而,在没有 FAT 时,链接分配不能支持髙效的直接访问,因为块指针与块一起分散在整个磁盘上,并且必须按序读取。索引分配通过将所有指针放在一起,即索引块,解决了这个问题。
每个文件都有自己的索引块,这是一个磁盘块地址的数组。索引块的第 i 个条目指向文件的第 i 个块。目录包含索引块的地址(图 4)。当查找和读取第 i 个块时,采用第 i 个索引块条目的指针。
图 4 磁盘空间的索引分配
当创建文件时,索引块的所有指针都设为 null。当首次写入第块时,先从空闲空间管理器中获得一块,再将其地址写到索引块的第 i 个条目。
索引分配支持直接访问,并且没有外部碎片问题,因为磁盘的任何空闲块可以满足更多空间的请求。然而,索引分配确实浪费空间。索引块指针的开销通常大于链接分配的指针开销。考虑一下常见情况,即一个文件只有一块或两块。采用链接分配,每块只浪费一个指针的空间。采用索引分配,即使只有一个或两个指针是非空的,也必须分配一个完整的索引块。
这一点提出了一个问题:索引块应为多大?每个文件必须有一个索引块,因此需要索引块尽可能小。然而,如果索引块太小,它不能为大的文件存储足够多的指针。因此,必须采取一种机制,以处理这个问题。此目的的机制包括:
链接方案:一个索引块通常为一个磁盘块。因此,它本身能直接读写。为了支持大的文件,可以将多个索引块链接起来。例如,一个索引块可以包括一个含有文件名的头部和一组头 100 个磁盘块的地址。下一个地址(索引块的最后一个字)为 null(对于小文件),或者另一个索引块的指针(对于大文件)。
多级索引:链接表示的一种变种是,通过第一级索引块指向一组第二级的索引块,它又指向文件块。当访问一块时,操作系统通过第一级索引查找第二级索引块,再采 用这个块查找所需的数据块。这种做法可以持续到第三级或第四级,具体取决于最大文件大小。对于 4096 字节的块,可以在索引块中存入 1024 个 4 字节的指针。两级索引支持 1 048 576 个数据块和 4GB 的最大文件。
组合方案:用于基于 UNIX 的文件系统,将索引块的前几个(如 15)指针存在文件的 inode 中。这些指针的前 12 个指向直接块;即它们包含存储文件数据的块的地址。因此,小的文件(不超过 12 块)不需要单独的索引块。如果块大小为 4KB,则不超过 48KB 的数据可以直接访问。接下来的 3 个指针指向间接块。第一个指向一级间接块。一级间接块为索引块,它包含的不是数据,而是真正包含数据的块的地址。第二个指向二级间接块,它包含了一个块的地址,而这个块内的地址指向了一些块,这些块中又包含了指向真实数据块的指针。最后一个指针为三级间接块指针。图 5 显示了一个 UNIX 的 inode。
图 5 UNIX 的 inode
采用这种方法,一个文件的块数可以超过许多操作系统所用的 4 字节的文件指针所能访问的空间。32 位指针只能访问 232 字节,或 4GB。许多 UNIX 和 Linux 现在支持 64 位的 文件指针。这样的指针允许文件和文件系统为数艾字节。ZFS 文件系统支持 128 位的文件 指针。
索引分配方案与链接分配一样在性能方面有所欠缺。尤其是,虽然索引块可以缓存在内存中,但是数据块可能分布在整个卷上。
7. 总结
本文到这里就结束啦~~
期待您的关注~~🥰🥰
猫猫陪你永远在路上💪💪
如果觉得对你有帮助,友友们可以点个赞,收个藏呀~