北邮 操作系统(八)

第八章 文件系统

CPU管理和内存管理构成了操作系统的核心kernal,通过外设管理用户可以用键盘和显示器进行输入和输出(可以将文件视图理解为文件系统的一个子集),本章将讨论构成一个完整的操作系统的最后一部分 —— 文件系统,用户对操作系统的使用都是以文件为基础的,无论是用户编辑的文档、执行的指令还是使用的外部设备在OS中都是文件,因此文件系统是构成操作系统的必要组成部分;

文件系统归根结底是对磁盘的驱动,因为在磁盘驱动的过程中发现直接使用磁盘非常繁琐,所以引入如下五层抽象:

  1. 从扇区到磁盘块的抽象;
  2. 从单个磁盘块请求到多个进程的磁盘请求队列;
  3. 从磁盘请求到高速缓存;
  4. 从盘块集合到文件的抽象;
  5. 从多个文件到构建文件系统;(看不懂?看不懂就对了,这就是下面我们会讲的)

操作系统通过上述五层抽象讲整个磁盘变成一系列文件,并将这些文件组织成树状结构,形成操作系统第二个基本的视图 —— 文件视图;

本章从磁盘驱动出发逐层揭开上述抽象过程;

1.磁盘简介

磁盘是一类较为特殊的I/O设备,也就是持久性存储设备,学习磁盘是接触文件系统的基础(因为文件系统的底层就是存储设备,且一般考虑块设备而不是字符设备),在本章的后面章节我们将基于磁盘讨论读写速度的优化和文件系统的设计


磁盘作为一种外部设备,其工作原理和一般外设工作原理完全一样:

  1. 从CPU开始,用户需要使用磁盘设备时,CPU发送命令给磁盘设备,通过"out ax,端口号"指令告诉磁盘具体的动作细节;
  2. 从磁盘开始,磁盘在工作完成之后使用磁盘中断告诉CPU,CPU将在中断处理程序中完成后续工作;

磁盘的构成:磁盘是由多个圆形盘面形成的盘面组,每个盘面上又有多个同心圆环,每个同心圆环被称为一个磁道,多个磁盘的同一磁道合在一起形成一个圆柱面,简称柱面。每个磁道再被分割为多个扇区,扇区是磁盘读写的基本单位。由于有多个盘面,所以在每个盘面上都有一个读写磁头,进行磁盘读写时,只有一个磁头是上电的,会读写该上电磁头对应的那个磁道上的那个扇区。

总结:一块磁盘有多个记录面,每个记录面有多条磁道,每条磁道被划分为多个扇区(也被称为块,块是磁盘最小的读写单位)

CPU使用磁盘的方法非常直观:让CPU给磁盘控制器发出读写命令,具体就是告诉磁盘控制器读写哪个柱面C、哪个磁头H、哪个扇区S以及要读写的内存缓存区的位置和读写长度即可。当然需要查阅硬件手册,找到这些信息对应的端口地址,一旦找到以后,CPU用out指令将这些信息写出去即可,磁盘控制器一旦看到了这些信息就会执行磁头滑动、磁盘旋转以及读写扇区等动作了。

磁盘读写的具体过程是:

(1)磁头移动,找到要读的那个柱面(cylinder,以下简称C),由于多个磁头是绑在一起移动的,所以每个磁头下面的磁道在各自的盘面中具有同样的位置,所有磁头下面的磁道从上到下组合在一起就形成了一个“柱面”;

(2)从柱面中选择要具体读写哪个磁道,实际上就是选择哪个磁头(magnetic head,以下简称H)上电;

(3)旋转磁盘,将对应磁道中要读写的那个扇区(sector,以下简称S)转到磁头的下方;

(4)开始读写,将扇区中的内容读到内存缓存区中,或者是将内存缓存区中的内容写出到该扇区中;

1.1 磁盘调度算法

参考链接:

2.磁盘驱动

2.1 第一层抽象

符合程序员使用习惯的磁盘读写是抹去C、H、S等具体细节,让程序员感觉是一堆扇区排成一排等待用户使用;

实现这种访问的核心是建立从C、H、S扇区地址到扇区号的一个映射,即建立一个在C、H、S基础之上的编址方案,该编址方案是文件系统第一层抽象的中心任务;

因为读写磁盘的时间主要花费在寻道上,所以最好的编址方案就是将逻辑上相邻的扇区在物理上也是在同一个磁道上且相邻;

完成了从C、H、S到扇区号的完整映射后,操作系统用户可以通过一个一维扇区编号来访问磁盘扇区而不需要再使用繁琐的C、H、S地址,也不需要记住磁头个数等硬件参数;

操作系统还做了另外一件令人匪夷所思的事情 —— 引入磁盘块作为用户读写磁盘的基本单位(磁盘块就是多个连续的扇区),为啥这么做?因为当使用磁盘块作为读写基本单位之后,只需要经过一次磁盘寻道和磁盘旋转就可以读写一块非常大的磁盘空间,这将提高磁盘的读写效率(这当然会产生一些碎片被浪费掉),这是一个用空间换时间的思路(现在的磁盘容量通常很大,不用过多的担心);

2.2 第二层抽象

经过第一层抽象之后,我们可以处理磁盘块的读写请求了;

操作系统中有多个进程,每个进程都会提出磁盘块访问请求,所以在实际操作系统中是多个进程产生多个磁盘块读写请求的情形。多个磁盘读写请求,需要用队列来组织这些请求,这就是操作系统对磁盘管理的第二层抽象;

经过第二层抽象以后,磁盘读写会变成这个样子:想进行磁盘读写的进程首先建立一个磁盘请求数据结构,并在这个数据结构中填上要读写的磁盘块号(简称盘块号),然后将这个数据结构放入磁盘请求队列中就完成了“磁盘读写”。剩下的工作交给操作系统来完成,对用户进程完全透明,操作系统要处理的工作如下:

(1)从队列中选择一个磁盘请求 —— 第二层抽象的核心,磁盘调度算法;

(2)取出请求读写的;

(3)根据盘块号计算出C、H、S;

(4)用out语句向磁盘控制器发出具体指令;

2.3 第三层抽象

整理一下到目前为止的磁盘处理过程:操作系统处理各个进程提出的磁盘请求,根据请求中的磁盘块号在磁盘上找到相应的扇区位置,将这些扇区读入到内核态内存中,然后再由系统调用
(如sys_read)将存放于内核态内存中的磁盘数据复制到用户态内存中,用户态程序操作用户态内存中的数据。

磁盘高速缓存能大幅度减少磁盘读写次数,是磁盘管理的又一层抽象,简单来说就是操作系统将磁盘数据“变成一系列位于内核态内存中的缓存区内容”;

简单分析一下磁盘高速缓存的工作原理:当用户发出一个磁盘块读写请求时,操作系统会在高速缓存中查找这个磁盘块是否已经在高速缓存中

  • 如果在就直接返回;
  • 如果发现高速缓存中没有用户请求的磁盘块,此时应该去读写物理磁盘;

所以高速缓存的关键是要提供一种机制来快速查找一个磁盘块数据是否在高速缓存中,根据关键字(盘块号)来快速查找其是否在一个表中,最常使用的数据结构就是散列表,因此以盘块号为关键字形成一个散列表来组织已经载入的磁盘块数据 —— 缓存块;

而当在物理磁盘中读写的情况下,这要求在高速缓存中取出一个空闲缓存块,用来缓存从磁盘块中读出的数据,组织空闲缓存块通常使用的数据结构就是空闲链表;

因此设计磁盘高速缓存的核心就是要建立两个数据结构:用一个散列表组织有内容的缓存块,再用一个空闲链接组织那些空闲的缓存块;

2.4 第四层抽象

抽象到现在,用户通过盘块号来调用bread函数,就可以读写磁盘了,看起来已经比较方便了。但是对于那些连磁盘是什么都不知道的大多数计算机用户而言,用磁盘块号来读写磁盘仍然不可行,因为这要求用户除了知道磁盘块的概念外,还需知道磁盘块大小这样一些“高级参数”。

为了让磁盘上的数据访问更符合人们的习惯,操作系统引出了磁盘使用的第四层抽象文件,文件是一个连续的字符流。为什么是字符流?因为不管是什么数据,也不管这个数据内容有多大,我们都将其看成是一个字符流。在这个字符流上读取、改写、插入、删除某个或某些字符,这才是符合人类习惯的数据访问方式。

操作系统的这一层抽象就是要将磁盘块抽象为一个字符流,经过抽象以后:

(1)用户看到并访问的是一个文件,是一个字符流,和磁盘块没有任何关系;

(2)从磁盘物理设备出发,磁盘中只有磁盘块,所以字符流最终还是要存放在磁盘块上;

(3)操作系统将字符流读写映射为对磁盘块的读写;

经过抽象之后,用户可以在这个字符流上随意滑动,随意处理,操作系统会根据一个映射表找到和字符流位置对应的磁盘块号,操作系统完成了从磁盘块到字符流的映射。显然,实现文件抽象的关键就在于能根据字符流位置找到对应的盘块号,即建立字符流和盘块号之间的映射关系。

顺序存储结构

链式存储结构

文件字符流存放的磁盘块不需要连续,只要每个磁盘块中存放下一个字符流片段所在的盘块号即可。这样就会形成一个“链”式结构;

索引存储结构

文件字符流被分割成多个逻辑块,在物理磁盘上寻找一些空闲物理盘块(无须连续),将这些逻辑块的内容存放进去,再找一个磁盘块作为索引块,其中按序存放各个逻辑块对应的物理磁盘块号

多阶索引存储结构

2.5 第五层抽象

引入了文件抽象以后,对磁盘的使用已经变成对文件的访问。抽象到现在,磁盘的使用更符合人们的直观感觉,并且在整个抽象过程中操作系统引入了高速缓存等提高磁盘读写效率的处理技术,磁盘使用的效率也有了大幅提升。

但是,现在还没有完成对整个磁盘的全部抽象。因为一个文件可以将磁盘上的一些磁盘块抽象成一个字符流,但是磁盘是很大的,不可能用一个文件完成对磁盘上所有物理盘块的抽象。另外,从给用户提供文件视图的角度出发,整个磁盘上也绝不可能只有一个文件,显示器对应一个文件,打印机也对应另一个文件。

本节的核心就是讲述操作系统如何组织多个文件(这里是多个文件,不是多个进程,注意和第二层抽象区分),磁盘中的文件按照树形结构组织,形成目录树;

实现磁盘的抽象就是实现目录树,那么实现目录树的关键又是什么呢?目录树由文件和目录两部分组成,实现目录树的关键就是实现目录;

3.文件系统概述

文件:一组有意义的信息/数据集合;

3.1 文件的属性

文件名:由创建文件的用户决定文件名,主要是为了方便用户找到文件,同一目录下不允许有重名文件;

标识符:一个系统内的各文件标识符唯一,对用户来说毫无可读性,因此标识符只是操作系统用于区分各个文件的一种内部名称;

类型:指明文件的类型;

位置:文件存放的路径(让用户使用)、在外存中的地址(操作系统使用,对用户不可见);

文件大小、创建时间、上次修改时间、文件所有者信息

保护信息:对文件进行保护的访问控制信息;

3.2 文件分类

文件可以分为如下两类:

  • 无结构文件(如文本文件),由一些二进制或字符流组成,又称“流式文件”;

  • 有结构文件(如数据库表),由一组相似的记录组成,又称“记录式文件”;

    • 记录是一组相关数据项的集合;
      • 记录由数据项组成,数据项是文件系统中最基本的数据单位;

3.3 文件系统的功能

4.文件的逻辑结构

所谓的“逻辑结构”,就是指在用户看来,文件内部的数据应该是如何组织起来的(下一节将介绍文件之间是如何组织的);而“物理结构”指的是在操作系统看来,文件的数据是如何存放在外存中的(可以类比数据结构的逻辑结构和物理结构);

因为无结构文件内部的数据就是一系列字符流,不存在明显的结构特性,故不需要讨论无结构文件的“逻辑结构”;

有结构文件指的是由一组相似的记录组成,又称“记录式文件”。每条记录又若干个数据项组成,如数据库表文件,一般来说,每条记录有一个数据项可作为关键字(作为识别不同记录的ID)。根据各条记录的长度(占用的存储空间)是否相等,又可分为定长记录和可变长记录两种;

根据有结构文件中的各条记录在逻辑上如何组织,可以将有结构文件分为三类:

  • 顺序文件
  • 索引文件
  • 索引顺序文件

4.1 顺序文件

顺序文件:文件中的记录一个接一个地顺序排列(逻辑上),记录可以是定长的或可变长的。各个记录在物理上可以顺序存储或链式存储。

根据记录之间的顺序是否与关键字相关,将顺序文件进一步分为:

  • 串结构:通常按照记录存入的时间决定记录的顺序;
  • 顺序结构:记录之间的顺序按照关键字顺序排列;

根据文件的特性,有如下结论:

4.2 索引文件

目的:解决可变长文件访问慢的问题,实现可变长文件随机访问的功能;

索引文件:每一个文件会建立一张索引表,每一张索引表的表项会对应该文件的一条记录,文件中的这些记录可以在物理上离散地存放,但是索引表的表项(一条记录)在物理上是需要连续存放的(另外需要注意的是每一个索引表的表项大小是相同的);

索引表本身是定长记录的顺序文件,因此可以快速找到第i个记录对应的索引项;

可将关键字作为索引号内容,若按关键字顺序排列,则还可以支持按照关键字折半查找;

每当要增加/删除一个记录时,需要对索引表进行修改;由于索引文件有很快的检索速度,因此主要用于对信息处理的及时性要求比较高的场合;

4.3 索引顺序文件

目的:解决索引表对存储空间的利用率很低的问题 —— 假如文件的每个记录平均只占8B,而每个索引表的表项占32B,这就导致索引表比文件本身还大;

索引顺序文件是索引文件和顺序文件思想的结合:索引顺序文件中,同样会为文件建立一张索引表,但不同的是,并不是每个记录对应一个索引表项,而是一组记录对应一个索引表项;

多级索引顺序文件:为了进一步提高检索效率,可以为顺序文件建立多级索引表;

5.文件目录

我们知道从用户的角度看文件之间的组织方式是按照文件目录(树结构)进行的,本节将详细讨论从操作系统的角度来看如何实现文件目录结构(很多地方将文件目录和目录文件混用,因此我们不需要做过多区分);

本节的知识图谱如下

5.1 文件控制块

目录(也称为文件夹、文件目录、目录文件)中的一条记录就是一个文件控制块FCB,FCB的有序集合称为“文件目录”,一个FCB就是一个文件目录项;

FCB中包含了文件的基本信息(文件名、物理地址、逻辑结构、物理结构等),存取控制信息(是否可读/可写、禁止访问的用户名单等),使用信息(如文件的建立时间、修改时间等);

FCB最核心的功能是实现了文件名和文件之间的映射,使得用户/用户程序可以实现“按名存取”;

文件目录主要实现以下功能:

5.2 目录结构

在操作系统的发展过程中出现了各种各样的目录结构

5.2.1 单级目录结构

早期操作系统并不支持多级目录,整个系统中只建立一张目录表,每个文件占一个目录项;

5.2.2 两级目录结构

早期的多用户操作系统,采用两级目录结构,分为主文件目录(MFD,Master File Directory)和用户文件目录(UFD,User Flie Directory);

5.2.3 多级目录结构

又称为树形目录结构,是现代操作系统中很常见的一种目录结构

很多时候,用户会连续访问同一目录内的多个文件(比如:接连查看“2015-08"目录内的多个照片文件),显然,每次都从根目录开始查找,是很低效的。因此可以设置一个“当前目录”,从当前目录的路径称为“相对路径”,引入“当前目录”和“相对路径”之后明显减少了磁盘的I/O次数,提升了访问文件的效率;

5.2.4 无环图目录结构

树形目录结构可以很方便地对文件进行分类,层次结构清晰,也能够更有效地进行文件的管理和保护,但是,树形结构不便于实现文件的共享,为此,提出了“无环图目录结构”;

可以用不同的文件名指向同一个文件,甚至可以指向同一个目录(共享同一目录下的所有内容);

删除目录:需要为每个共享结点设置一个共享计数器,用于记录此时有多少个地方在共享该结点。用户提出删除结点的请求时,只是删除该用户的FCB、并使共享计数器减1,并不会直接删除共享结点;只有共享计数器减为0时,才删除结点;

注意:共享文件不同于复制文件。在共享文件中,由于各用户指向的是同一个文件,因此只要其中一个用户修改了文件数据,那么所有用户都可以看到文件数据的变化。

5.3 索引结点

本质上是对FCB数据结构的改进

当找到文件名对应的目录项时,才需要将索引结点调入内存,索引结点中记录了文件的各种信息,包括文件在外存中的存放位置,根据“存放位置”即可找到文件;

存放在外存中的索引结点称为“磁盘索引结点”,当索引结点放入内存后称为“内存索引结点”;相比之下内存索引结点中需要增加一些信息,比如:文件是否被修改、此时有几个进程正在访问该文件等;

6.文件的物理结构*

本节解决的问题:从上往下看,文件数据应该怎么存放在外存(磁盘)上,文件的物理结构也称为文件的分配方式;

操作系统对磁盘进行的管理主要分为:

  • 对非空闲磁盘块的管理(存放了文件数据的磁盘块) —— 文件的物理结构/文件分配方式(本节解决);
  • 对空闲磁盘块的管理 —— 文件存储空间管理;

文件的物理结构主要探讨的就是文件数据应当怎样存放在外存中,在开始本节知识点之前需要介绍几个前置知识点

文件块/磁盘块

物理地址空间:类似于内存分页,磁盘中的存储单元也会被分为一个个“块/磁盘块/物理块”。很多操作系统中,磁盘块的大小与内存块、内存页的大小相同(外存的物理地址表示为(物理块号,块内地址));

逻辑地址空间:在内存管理中,进程的逻辑地址空间被分为段地址:段内偏移(分段,但是如果我们引入“块”的概念(Cache块,分页和分块的中间层),那么就可以将进程的逻辑地址表示为(逻辑块号,块内地址));同样的,在外存管理中,为了方便对文件数据的管理,文件的逻辑地址空间被分为了一个一个的文件“块”,于是文件的逻辑地址也可以表示为(逻辑块号,块内地址)的形式;

操作系统负责实现将文件的逻辑地址空间与物理地址空间进行映射(这也是本小节的核心问题);

6.1 连续分配

概念

FCB

连续分配方式下文件目录需要记录的关键文件属性如下,这是为了实现之后地址映射

地址映射

采用连续分配方式的地址转换方式(逻辑块号,块内地址)->(物理块号,块内地址):只需转换块号就行,块内地址保持不变;

用户给出要访问的逻辑块号,操作系统找到该文件对应的目录项(FCB),利用公式 物理块号=起始块号+逻辑块号 进行计算;

小结

优点:

  • 使用连续分配方式可以直接算出逻辑块号对应的物理块号,因此连续分配支持顺序访问和直接访问(即随机访问);
  • 连续分配的文件在顺序读/写时速度最快;

缺点:

  • 物理上采用连续分配的文件不方便拓展;
  • 物理上采用连续分配,存储空间利用率低,会产生难以利用的磁盘碎片;可以用紧凑来处理碎片,但是需要耗费很大的时间代价;

6.2 链接分配

链接分配采取离散分配的方式,可以为文件分配离散的磁盘块,分为隐式链接和显式链接两种;

6.2.1 隐式链接

考试中出现的“链接分配”默认是隐式链接分配;

概念

FCB

隐式链接分配方式下文件目录需要记录的关键文件属性如下

地址映射

用户给出要访问的逻辑块号i,操作系统找到该文件对应的目录项(FCB);

从目录项中找到起始块号(即0号块),将0号逻辑块读入内存,由此知道1号逻辑块存放的物理块号,于是读入1号逻辑块,再找到2号逻辑块的存放位置以此类推;

因此,读入i号逻辑块,总共需要i+1次磁盘I/O;

小结

优点:很方便文件拓展,不会有碎片问题,外存利用率高;

缺点:只支持顺序访问,不支持随机访问,查找效率低,指向下一个盘块的指针也需要耗费少量的存储空间;

6.2.2 显式链接

把用于链接文件各物理块的指针显式地存放在一张表中,即文件分配表(FAT,File Allocaticn Table)

概述

FCB

地址映射

用户给出要访问的逻辑块号i,操作系统找到该文件对应的目录项(FCB);

从目录项中找到起始块号,若i>0,则查询内存中的文件分配表FAT,往后找到i号逻辑块对应的物理块号,逻辑块号转换成物理块号的过程不需要读磁盘操作(FAT常驻内存);

小结

优点:很方便文件拓展,不会有碎片问题,外存利用率高,并且支持随机访问。相比于隐式链接来说,地址转换时不需要访问磁盘,因此文件的访问效率更高;

缺点:文件分配表的需要占用一定的存储空间;

6.3 索引分配

索引分配允许文件离散地分配在各个磁盘块中,系统会为每个文件建立一张索引表,索引表中记录了文件的各个逻辑块对应的物理块(索引表的功能类似于内存管理中的页表 —— 建立逻辑页面到物理页之间的映射关系);

磁盘中用于存放索引表的磁盘块被称为索引块,磁盘中用于存放文件实际数据的磁盘块被称为数据块;

概述

FCB

地址映射

用户给出要访问的逻辑块号i,操作系统找到该文件对应的目录项(FCB);

从目录项中可知索引表存放位置,将索引表从外存读入内存,并查找索引表即可只i号逻辑块在外存中的存放位置;

拓展

一个磁盘块的大小是有限的,相应的能够存储的索引项也是有限的,在某些情况下仅使用一个磁盘块是不能装下整个文件的索引表的(即索引块不只一个磁盘块的大小),主要有以下解决方案;

  • 链接方案:如果索引表太大,一个索引块装不下,那么可以将多个索引块链接起来存放;

缺点:若文件很大,索引表很长,就需要将很多个索引块链接起来。想要找到i号索引块,必须先依次读入0~i-1号索引块,这就导致磁盘1/0次数过多,查找效率低下;

  • 多层索引:建立多层索引(原理类似于多级页表),使第一层索引块指向第二层的索引块,还可根据文件大小的要求再建立第三层、第四层索引块;

关于为什么每个索引表的大小不能超过一个磁盘块,因为255指向的是二级索引表而不是下一个一级索引表(至于为什么不单独把最后一个二级索引表当作一级索引表以拓展索引表大小,应该是二级索引表仍然能够起到拓展大小的作用,无需复杂化,因为多层索引表本来就是为了解决单层索引表的缺点诞生,是优化关系而不是并列关系)

采用K层索引结构,且顶级索引表未调入内存,则访问一个数据块只需要K+1次读磁盘操作;

缺点:即使是小文件,访问一个数据块依然需要K+1次读磁盘;

  • 混合索引:多种索引分配方式的结合;例如,一个文件的顶级索引表中,既包含直接地址索引(直接指向数据块),又包含一级间接索引(指向单层索引表)、还包含两级间接索引(指向两层索引表);

注意:各索引表最大不能超过一个块的大小;

优点:对于小文件,只需较少的读磁盘次数就可以访问目标数据块(一般计算机中小文件更多);

7.文件存储空间管理

对存储空间的管理实际上就是对空闲磁盘块的管理;

可以将将物理磁盘划分为一个个文件卷(逻辑卷、逻辑盘,如C、D、E盘),文件卷可以划分为目录区和文件区,目录区主要用于存放文件目录信息FCB以及用于进行磁盘存储空间管理的信息,文件区主要用于存放文件数据;

7.1 空闲表法

在学习这几个经典的存储空间管理方法的时候我们时刻提出并解决以下问题:

  1. 操作系统用什么方式/数据结构记录、组织空闲块?
  2. 如何分配磁盘块?
  3. 如何回收磁盘块?

空闲表法适用于文件的物理结构是连续分配的情况;

7.2 空闲链表法

7.2.1 空闲盘块链

以盘块为单位组成一条空闲链

7.2.2 空闲盘区链

以盘区(连续的盘块)为单位组成一条空闲链,对离散分配、连续分配都适用,与空闲盘块链相比为一个文件分配多个盘块时效率更高;

7.3 位示图法

用二进制位对应盘块是否已分配的信息,对连续分配和离散分配都适用;

7.4 成组链接法

空闲表法、空闲链表法不适用于大型文件系统,因为空闲表或空闲链表可能过大,UNIX系统中采用了成组链接法对磁盘空闲块进行管理;

文件卷的目录区中专门用一个磁盘块作为“超级块”,当系统启动时需要将超级块读入内存,并且要保证内存与外存中的“超级块”数据一致;

需要注意的是,每个分组被分配之前需要将该分组的链接信息复制到超级块中,超级块充当了一个链头的作用,在该链头中永远要保持指向下一个分组的信息;

8.文件的基本操作

8.1 创建文件

8.2 删除文件

8.3 打开文件

8.4 关闭文件

8.5 读文件

8.6 写文件

8.7 文件共享

操作系统为用户提供文件共享功能,可以让多个用户共享地使用同个文件;

主要有两种实现方式:

  • 基于索引结点的共享方式(硬链接);
  • 基于符号链的共享方式(软链接);

注意:多个用户共享同一个文件,意味着系统中只有“一份”文件数据。并且只要某个用户修改了该文件的数据,其他用户也可以看到文件数据的变化;

8.7.1 硬链接

索引结点,是一种文件目录瘦身策略。由于检索文件时只需用到文件名,因此可以将除了文件名之外的其他信息放到索引结点中。这样目录项就只需要包含文件名、索引结点指针;

索引结点中设置一个链接计数变量count,用于表示链接到本索引结点上的用户目录项数。若count=2,说明此时有两个用户目录项链接到该索引结点上,或者说是有两个用户在共享此文件;

若某个用户决定“删除”该文件,则只是要把用户目录中与该文件对应的目录项删除,且索引结点的count值减1;

若count=0,说明还有别的用户要使用该文件,暂时不能把文件数据删除,否则会导致指针悬空;

8.7.2 软链接

Link类型的文件记录了对应文件的存放路径,类似于Windows操作系统中的快捷方式;

8.8 文件保护

8.8.1 口令保护

为文件设置一个“口令”(如:abc112233),用户请求访问该文件时必须提供“口令”;口令一般存放在文件对应的FCB或索引结点中。用户访问文件前需要先输入“口令”操作系统会将用户提供的口令与FCB中存储的口令进行对比,如果正确,则允许该用户访问文件;

优点:保存口令的空间开销不多,验证口令的时间开销也很小;
缺点:正确的“口令”存放在系统内部,不够安全;

8.8.2 加密保护

使用某个“密码”对文件进行加密,在访问文件时需要提供正确的“密码”才能对文件进行正确的解密;

优点:保密性强,不需要在系统中存储“密码”;
缺点:编码/译码,或者说加密/解密要花费一定时间;

8.8.3 访问控制

在每个文件的FCB(或索引结点)中增加一个访问控制列表(Access-Control List,ACL),该表中记录了各个用户可以对该文件执行哪些操作;

精简的访问列表:以“组”为单位,标记各“组”用户可以对文件执行哪些操作。如:分为系统管理员、文件主、文件主的伙伴、其他用户几个分组;当某用户想要访问文件时,系统会检查该用户所属的分组是否有相应的访问权限;

9.文件系统的层次结构

  • 用户接口(文件的基本操作):文件系统需要向上层的用户提供一些简单易用的功能接口。这层就是用于处理用户发出的系统调用请求(Read、Write、Open、Close等系统调用);

  • 文件目录系统(文件目录):用户是通过文件路径来访问文件的,因此这一层需要根据用户给出的文件路径找到相应的FCB或索引结点。所有和目录、目录项相关的管理工作都在本层完成,如:管理活跃的文件目录表、管理打开文件表等;

  • 存取控制模块(文件保护):为了保证文件数据的安全,还需要验证用户是否有访问权限。这一层主要完成了文件保护相关功能;

  • 逻辑文件系统与文件信息缓冲区(文件的逻辑结构):用户指明想要访问文件记录号,这一层需要将记录号转换为对应的逻辑地址;

  • 物理文件系统(文件的物理结构):这一层需要把上一层提供的文件逻辑地址转换为实际的物理地址;

    • 辅助分配模块(文件存储空间管理):负责文件存储空间的管理,即负责分配和回收存储空间;
    • 设备管理模块(磁盘管理):直接与硬件交互,负责和硬件直接相关的一些管理工作。如:分配设备、分配设备缓冲区、磁盘调度、启动设备、释放设备等;

10.常见文件系统

文章参考:09 文件与内存 - 简书 (jianshu.com)(这一章的内容在教材上根本找不到,只有在互联网上有一些零碎的知识点,还好这里找到了相对完整的文章);

视频参考:一文彻底搞懂文件系统。文件系统,跪下!23计算机考研操作系统复盘之文件系统_哔哩哔哩_bilibili(适合最后复习的时候回顾总结);

本节介绍的内容是集成了之前介绍的文件系统的所有的知识点,可能会有重复的内容,但是这些重复的内容恰好就是重要的点;


文件系统实际就是操作系统管理持久性存储数据的方法,它的基础是文件的抽象、存储设备管理和存储区域分配算法(内存分配);

10.1 FAT文件系统

FAT 的全称是 File Allocation Table,即文件配置表;

顾名思义,这种文件系统的核心是一个文件配置表,表中的每一项都对应着磁盘中一个实际的数据块;这个数据块可能包含了多个扇区,其大小由操作系统决定,因此它被成为逻辑数据块,以便于与物理扇区做出区分;

每个文件至少拥有一个数据块,因此我们可以通过文件在系统中的“编号”寻找表中对应的项,每一项都以链表的形式存储了同一个文件下一个数据块对应项的位置,如果其存储值为 -1 则代表这是这个文件的最后一个数据块;在寻找一个文件时,我们先进入这个配置表的第一项,也就是代表了根目录的数据块,从中找到根目录中存储的子目录或文件对应的项的编号;

FAT 中所有的空闲分区也被以链表的形式存储在配置表中,因此当我们需要延长一个文件时,我们就可以从链表中选取第一项;当一个文件被删除时,我们将它所占有的所有数据块都接入这个空闲分区链表中;

FAT文件系统的缺点:

如果我们选择较小的逻辑数据块大小,那么一个大型文件就会包含很多个小分区,由于 FAT 文件系统给文件分配的物理数据块不一定是连续的,这样的结构会导致读写效率很低;然而,如果我们转而选择较大的逻辑数据块,那么针对一些小文件的存储就会产生很多内部碎片;

FAT 文件系统下大文件和小文件的读写效率都不高,且它没有利用磁盘连续读写时速度快的优势,因此连续读写和随机读写的表现都较为糟糕;

特点:

  • FAT系统中所有目录都存储在文件系统中的第一个数据扇区中;

10.2 FFS文件系统

FAT 是一个效率不高的文件系统,且它不包括控制使用权限等对于系统安全来讲至关重要的功能;

为了充分利用磁盘连续读写时速度较快的优势、提高读写文件的效率、并存储更多与文件相关的元数据(Metadata,即表示文件特点、而非文件内容的数据),我们需要一种新的文件系统设计,这种新的文件系统就是 BSD Fast File System,也就是 Unix 中使用的文件系统;

由于磁盘中数据的最小存储单位是一个扇区,我们可以自然地想象到,一个文件需要记录其数据对应着哪些磁盘扇区,但如果我们在同一个扇区里记录所有数据扇区的序号,那么一个文件的大小就被一个扇区能够存储的序号数量乘以单个扇区的大小限制了。这种大小限制会限制文件系统的实用性——研究表明,虽然大多数文件都是较小的文件,但文件系统中占据较大部分空间的都是较大的文件,因此我们需要能够处理大文件的情况。然而,如果我们单纯使用两到三个扇区来存储所有数据扇区的序号,在存储小文件时这种结构又会浪费很多空间。为了防止这种问题的出现,我们需要一个“伸缩自如”的结构;

FFS 就发明了这样一种结构。在 FFS 中,每个文件都被一个 inode (即之前介绍的索引节点)代表。这个 inode 中存储的是文件的元数据和数据扇区的指针,但是与一般指针不同的是,inode 中不只包含直接指向数据扇区的指针,还包含二层指针和三层指针。二层指针指向的扇区中包含的不是数据、而是指向数据扇区的指针;以此类推,三层指针指向的扇区包含的是指向二层指针扇区的指针。这样假如我们的一个扇区原本可以存储 n 个指针,现在我们就可以通过二层指针存储 n2 个指针。不过,由于大多数文件都是小文件,FFS 对于 inode 中二层指针和三层指针的数量作出了限制,大多数指针仍然是直接指针;

特点:

  • FFS将文件的元数据存储在inode中,方便在打开文件时查看权限等数据;
  • 由于inode的存在,FFS在存储小文件时效率可能不高;
  • FFS 相比FAT来讲,由于其引入了二层指针和三层指针,存储大文件的效率更高,但这一结构也增加了我们在获得文件数据时访问磁盘的次数;

10.3 NTFS文件系统

NTFS文件系统在 Windows 系统中取代了 FAT 成为了新一代文件系统;

在 NTFS 系统中,整个文件系统被包括在一个叫做 Master File Table 的表格中,其中每一项都代表一个文件的记录,其中包含了每个文件的名称、标准信息,如创建时间、编辑时间等,它也可以包含文件数据本身;这样,一个小文件的数据就可以直接储存在 Master File Table 中,不浪费多余的空间;对于大文件来讲,代表大文件的表项中的数据包含了许多对“属性:值”,其中可以有多对由数据块指向起始扇区和长度的信息,这样的“属性:值”对也可以被用来将多个表项串联起来,用来存储更大的文件;

特点:

  • 如果没有目录结构的存在,那么NTFS的效率可能不比FAT高;
  • NTFS 与FFS 在处理数据时都使用了树状结构来提升效率;在NTFS 中,树状结构表现在目录的B-Tree结构中;在FFS中,树状结构表现在inode中数据扇区的多层指针中;
  • NTFS 与FFS 相比,存储小文件的效率更高;由于NTFS 可以将小文件的数据直接存储在Master File Table中,且没有inode的大小限制,其效率更高;
  • NTFS的优势在于每个表项中都可以用“属性:值”的配对延长文件长度,因此文件长度变化较为灵活;

10.4 虚拟文件系统

日常生活中使用的存储设备如U盘、移动硬盘等都有自己的文件系统,但我们在将这些设备接入到计算机中时、它们仍然可以作为我们计算机中文件系统的一部分被浏览。用于实现这一功能的过程集叫做挂载(mount);在一台设备上可能存在多个文件系统,每个可以独立存在的文件系统就被称为“卷”(Volume);当一个设备被插入到计算机中时,操作系统会先识别设备上存在的文件系统,然后将这些文件系统挂载到操作系统自带的文件系统下;

如果操作系统自带的文件系统与设备上的文件系统版本不同(当然也不一定是版本不同,反正可能就是出现各种问题),那么操作系统如何才能兼容这个设备上的系统呢?

一种简单的方法是针对每个不同的文件系统写一段用于兼容的代码,但这种解决方法的效率显然不高,而且很难维护——每当一种新的文件系统出现时,我们都需要更新操作系统的代码;

在计算机这一领域中,解决这类问题有一个常见的方法,那就是增加一个新的抽象层,因为一个新的抽象层可以使我们在不考虑更底层的抽象层的细节的前提下实现我们需要的功能;

在文件系统中,这个新的抽象层就是 虚拟文件系统(Virtual File System,VFS);虚拟文件系统基于一个类似于 inode 的概念, vnode,定义了一个使用文件的界面,所有实现这一界面的文件系统无论实现方式多么不同都能够被支持 VFS 的系统方便地读写、使用;不仅如此,vnode 不同于 inode,它的编号在整个网络上都是唯一的,因此它可以被用来支持远程文件系统;

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坂.y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值