EagleBear2002 的博客

这里必须根绝一切犹豫,这里任何怯懦都无济于事

计算机与操作系统-05-文件管理

本文主要内容来自 SpriCoder的博客,更换了更清晰的图片并对原文的疏漏做了补充和修正。

文件的概念

文件是由新消息按一定结构组成,可持久化保存的抽象机制,由于它必定存储在某种设备上,故也可以认为文件是设备的一种抽象。

文件由文件名标识,用户通过文件名就可以对文件进行访问。

文件(document)与计算机文件(file)的区别

文件的命名

文件名是字母、数字或其他符号组成的字母数字串,其格式和长度因系统而异。

文件命名一般包括文件名和扩展名

前者用于识别文件,后者用于标识文件特性,两者之间用.隔开。

每个 OS 都有约定的扩展名,Windows 中:

  1. .COM 表示可执行的二进制代码文件
  2. .EXE 表示可执行的浮动二进制代码文件
  3. .LIB 表示库程序文件
  4. .BAT 表示批命令文件
  5. .OBJ 表示编译或汇编生成的目标文件

UNIX 的约定文件名,请大家自己阅读。

文件的分类

  1. 用途可分成:系统文件、库文件、用户文件
  2. 保护级别可分成:只读文件、读写文件、不保护文件
  3. 信息时限可分成:临时文件、永久文件、档案文件
  4. 设备类型可分成:磁盘文件、磁带文件、光盘文件、软盘文件
  5. 还可以按文件的逻辑结构或物理结构分类
  6. Linux 系统支持文件:普通文件、目录文件、特殊文件(外部设备文件,可分为块设备文件和字符设备文件)

引入文件的优点 *

  1. 用户使用方便,使用者无需记住信息存放在辅助存储器(外存)中的物理位置,也无需考虑如何将信息存放到存储介质上,只要知道文件名,给出有关操作系统要求便可存取信息,实现了“按名存取”
  2. 文件安全可靠,由于用户通过文件系统才能实现对文件的访问,而文件系统能提供各种安全、保密和保护措施,故可防止对文件信息的有意或无意的破坏或窃用
  3. 系统能有效地利用存储空间(文件可备份),优化安排不同属主的文件的位置,如果文件使用过程中出现设备故障,系统组织重执或恢复,对因硬件失效而可能造成的信息破坏可组织转储以加强可靠性。
  4. 文件可共享,文件系统还能提供文件的共享功能,如不同的用户可以使用同名或异名的同一文件,提高了文件和文件空间的利用率
  5. 总之,把数据组织成文件形式加以管理和控制是计算机数据管理的重大进展

文件系统及其功能

文件系统的概念

文件系统是操作系统中负责存取和管理信息的模块,它用统一的方式管理用户和系统信息的存储、检索、更新、共享和保护,并为用户提供一整套方便有效的文件使用和操作方法。

通常把文件与管理信息资源的管理程序的集合,是操作系统中负责存取和管理信息资源的模块,采用统一方法管理用户信息和系统信息的存储、检索、更新、共享和保护,并为用户提供一整套行之有效的文件使用及操作系统。

文件系统中的文件

文件这一术语不但反映了用户概念中的逻辑结构,而且和存放它的辅助存储器(也称文件存储器)的存储结构紧密相关。

所以,同一个文件必须从逻辑文件物理文件两个侧面来观察它。

  1. 对于用户,需要并遵守文件系统的规则来定义文件信息的逻辑结构,由文件系统提供按名存取方式来实现对文件信息的存储和检索。
  2. 对于系统,必须采用特定数据结构和有效算法实现文件的逻辑结构到存储结构的映射,实现对文件存储空间和文件信息的管理,提供多种存取方法。

文件系统的功能

文件系统面向用户的功能是:

  1. 文件的按名存取
  2. 文件的共享、保护和加密
  3. 文件的操作和使用(文件的查找和定位)

为了实现这些功能,OS 必须考虑:

  1. 文件目录的建立和维护
  2. 存储空间的分配和回收
  3. 数据的保密和保护
  4. 监督用户存取和修改文件的权限
  5. 实现在不同存储介质上信息的表示方式、编址方法、存储次序,以及信息检索等问题
  6. 实现从逻辑文件到物理文件的转换
  7. 提供文件的存取方法和文件存储结构
  8. 提供给一组易用的文件操作和命令
  9. 提供与设备管理交互的统一接口

文件系统的组成

文件组织与存储

卷和块

文件存储介质有磁带、光盘和磁盘。

是存储介质的物理单位,对应于一盘磁带、一块软盘、一个光盘片、一个硬盘分区。

是存储介质上连续信息所组成的一个区域,也叫做物理记录

  1. 块是主存储器和辅助存储器进行信息交换的物理单位,每次总是交换一块或整数块信息
  2. 决定块的大小要考虑用户使用方式、数据传输效率和存储设备类型等多种因素
  3. 不同类型的存储介质,块的长短常常各不相同;对同一类型的存储介质,块的大小一般相同,但也可以不同

外围设备由于启停机械动作或识别不同块的要求,两个相邻块之间必须留有间隙,间隙是块之间不记录用户代码信息的区域

顺序存取存储设备的信息安排

  1. 顺序存取设备是严格依赖信息的物理位置次序进行定位和读写的存储设备
  2. 磁带机是最常用的一种顺序存取存储设备,它具有存储容量大、稳定可靠、卷可装卸和便于保存等优点,广泛用作存档
  3. 磁带的一个突出特点块长的变化范围较大,块可以很小,也可以很大,原则上没有限制
  4. 光盘也是一种顺序存取存储设备,光盘上的磁道不是同心圆,而是螺旋形的,本质的线性的。

直接存取存储设备的信息安排

  1. 磁盘是一种直接存取存储设备,又叫随机存取存储设备
  2. 移臂与旋转两维组织,存取速度高;
  3. 它的每个物理记录有确定的位置和唯一的地址,存取任何一个物理块所需的时间几乎不依赖于此信息的位置。

文件的逻辑结构

独立于物理环境的,用户概念中的抽象信息组织方式文件的逻辑结构

用户能观察到的,并加以处理的数据集合构成逻辑文件

文件的逻辑结构分为两种形式:

  1. 一种是流式文件
  2. 一种是记录式文件

流式文件

流式文件无结构文件,指文件内的数据不再组成记录,只是由一串依次的字节组成的信息流序列,称为字节流文件

这种文件常常按长度来读取所需信息,也可以用插入的特殊字符作为分界,使用读写指针访问。

大多数现代操作系统比如 Linux 系统只提供流式文件。

记录式文件

记录式文件是一种有结构的文件,它是若干逻辑记录信息所组成的记录流文件

逻辑记录是文件中按信息逻辑上的独立含义所划分的信息单位

如:每个职工的工资信息是一个逻辑记录;整个单位职工的工资信息便组成了该单位工资信息的记录式文件

逻辑记录是文件内独立的最小信息单位,文件记录位置代替字节位置。

记录是文件常用的记录组织和使用方法:

  1. 记录式顺序文件:文件的记录顺序生成并被顺序访问。
  2. 记录式索引文件:文件使用索引表,表项包含记录键和索引指针,记录键由应用程序确定,而索引文件便指向相应记录。

记录式文件与数据库

  1. 数据库管理系统也支持逻辑记录
  2. 但数据库有别于记录式文件,数据库中的记录之间可以通过数据冗余构成某种联系
  3. 数据库管理系统支持基于联系的数据查询,文件系统则不行

记录的成组与分解

成组与分解的提出

逻辑记录是按信息在逻辑上的独立含义由用户所划分的单位

块是系统划分的存储介质上连续信息所组成的区域。

  1. 一条逻辑记录被存放到文件存储器的存储介质上时可能占用一个或多块,或者一个物理块包含多条逻辑记录。
  2. 扇区也叫做物理块,或者物理记录

组:若干逻辑记录的组合。

块因子:每块中逻辑记录的个数。比如物理块 800K,卡片 80K,此时的块因子数就是 10。

对于流式文件,一个物理记录可以存放很多个连续字节。

成组与分解操作

  1. 系统设置独立于用户数据区的输入/输出缓冲区
  2. 记录的成组操作:在输出缓冲区内进行,凑满一块后才将缓冲区内的信息写到存储介质上
  3. 记录的分解操作:当存储介质上的一个物理记录读进输入缓冲区后,把逻辑记录从块中分离出来的操作

成组与分解的特征

优点:记录成组与分解不仅节省存储空间,还能减少输入输出操作次数,提高系统效率。

记录成组与分解处理带来的新特征:

  1. 提前读:用户读请求,导致包含该逻辑记录的物理块读入输入缓冲区;这一操作可能读入了多个逻辑记录,可以更快的访问附近的记录。
  2. 推迟写:用户写请求,首先是写入输出缓冲区,只有当该缓冲区中的逻辑记录满后才会引起实际输出。f 副作用:因为优先写到输出缓冲区,等到缓冲区满,才会写到磁盘,可能会造成数据不一致(写到缓冲区,但是因为停电等原因没有办法同步到磁盘)

记录格式

  1. 逻辑记录的长度:一条逻辑记录中所有数据项长度的总和。
  2. 记录格式:记录内数据的排列方式。
  3. 记录式文件中,记录长度取决于应用程序的需要,记录格式有
    1. 定长记录
    2. 变长记录
    3. 跨块记录

定长记录

  1. 记录式文件中所有的逻辑记录具有相同长度,同时所有数据项的相对位置也是固定的。
  2. 处理方便,易于控制:成组除了最后一块,块内逻辑记录个数相同。

变长记录

  1. 记录式文件中所有的逻辑记录长度不相等,但每条逻辑记录长度处理前能预先确定。逻辑记录中的第一个字段指明单个变长逻辑记录的字节数,第二个字段存放记录信息。
  2. 导致变长记录的情况
    1. 包含一个或多个可变长度的数据项。
    2. 包括可变数量的定长数据项。
  3. 处理复杂,但是节省存储空间。

跨块记录

  1. 逻辑记录长度大于块大小,不需要记录块长度,文件系统自动分割和装配跨块逻辑记录的信息段。
  2. 分割存储,读出装配、
  3. 适用于在不同物理特性的设备类型之间传输时。

记录键

  1. 记录键:用于标识某条逻辑记录的数据项,叫关键字,简称键。
  2. 在同一个文件中,能够唯一表示某条逻辑记录的记录键称为主键。
  3. 主键是最重要的,但是并不一定唯一。

文件的物理结构

文件的物理结构和组织是指逻辑文件在物理存储空间中的存放方法和组织关系

  1. 此时文件看做物理文件,即相关物理块的集合;
  2. 文件的存储结构涉及块的划分、记录的排列、索引的组织、信息的搜索等许多问题。

文件存储结构的优劣直接影响文件系统的性能。

构造文件物理结构

计算法:

  1. 设计映射算法,通常有线性计算法、杂凑法等,通过对记录键进行计算转换成对应的物理地址,从而找到所需记录。
  2. 直接寻址文件、计算寻址文件和顺序文件均属于此类。
  3. 存取效率高,不必增加存储空间存放附加控制信息。

指针法:

  1. 设置专门指针,指明相应记录的物理地址或表达各记录之间的关联。
  2. 索引文件、索引顺序文件、连接文件均属于此类。
  3. 可以将文件信息的逻辑次序与在存储介质上的物理块排列次序完全分开,便于随机存储,便于更新,但是消耗存储空间。

顺序文件

将一个文件中逻辑上连续的信息存放到存储介质的依次相邻的块中便形成顺序结构,这类文件叫顺序文件,又称连续文件

FCB 保存第一个物理块地址和总块数。

磁带文件、光盘文件是典型例子,批处理文件,系统文件用得最多

顺序文件的特点:

  1. 优点:顺序存取记录时速度快
  2. 缺点:建立文件前需要预先知道文件长度,修改、插入和添加文件记录困难,变长记录处理困难,空闲块的浪费。

连接文件

连接文件,又称串联文件,输入井、输出井都是此类文件。使用连接字(指针)来表示文件中各条记录之间的关系。

第一块文件信息的物理地址由文件目录给出, 而每一块的连接字指出了文件的下一个物理块位置;连接字内容为 0 时,表示文件至本块结束。

连接文件的特点:

  1. 优点:易于对文件记录做增、删、改,易于动态增长记录;不必预先确知文件长度;存储空间利用率高;
  2. 缺点:存放指针需额外的存储空间;由于存取须通过缓冲区,待获得连接字后,才能找到下一物理块的地址,因而,仅适用于顺序存取。

直接文件

直接文件、散列文件或哈希文件:在直接存取存储设备上,利用哈希法将记录的关键字与其地址之间建立某种对应关系,以便实现快速存取的文件

在 Linux 系统中,常用哈希法实现 cache。

计算寻址结构可能出现“冲突”,即不同的关键字可能变换出相同的地址来,解决办法是溢出处理技术,包含有链表法、循环探查法、二次散列法、溢出区法等。

访问过程:

  1. 构造哈希函数:得到哈希后块号 A
  2. 建立目录文件,将记录放置到对应的块 A 中
  3. 查找文件:根据文件名,计算出 A,然后加载物理块,在物理块中遍历找到对应文件。
  4. 溢出处理:结合溢出处理技术。

索引文件

索引文件为每个文件建立了一张索引表,每个表目包含一个记录的键(或逻辑记录号)及其存储地址。索引表记录方式有多种:

  1. 记录组成文件的磁盘块号,适用于流式文件。
  2. 所以表项包含记录键及其磁盘块号,适用于记录式文件。

索引文件:利用索引表来搜索记录的文件。

索引表可存放在 FCB 文件中,记录可以散列存储。

适用于数据记录保存在磁盘上的文件。

索引文件的访问方式

索引文件在文件存储器上分两个区:索引区和数据区

访问索引文件需两步操作

  1. 第一步查找索引表
  2. 第二步获得记录物理地址

需要两次访问辅助存储器,若文件索引已预先调入主存储器,那么,就可减少一次内外存信息交换。

索引文件的特点

索引结构可以被认为是连接结构的一种扩展,除了具备连接文件的优点外,还克服了它只能作顺序存取的缺点,具有直接读写任意一个记录的能力,便于文件的增、删、改。

索引顺序文件顺序文件的一种扩展。

索引文件的缺点是:增加了索引表的空间开销和查找时间

索引表的组织(重要)

  1. 一级索引:存放的是物理地址
  2. 两级索引:若干索引本身也是一种记录。
  3. 多级索引:以三级索引为例,一个地址指引 \(128^3\) 个地址,但是全部使用三级索引也不行,性能会比较差,所以我们往往选择使用混编的方式。
  4. 动态扩容:放不下就扩容

  1. inode 规定了 15 个索引项,每项 4KB
    1. 直接索引:前 12 项存放文件信息的磁盘块号
    2. 一次间接索引:第 13 项指向一个物理块
    3. 二次间接索引:第 14 项指向一个物理块
    4. 三次间接索引:第 15 项指向一个物理块
    5. ext2 中,每个物理块存放 1024B,所以上面右图最多存放\(12KB + 256KB + 256^2KB+256^3KB\)
  2. 长度不超过 12 个磁盘块的占 80%,只有超过 12 个磁盘块才使用简介索引。
  3. 多级索引例子(重要):注意是从 0-128 一共 129 项

文件的目录结构

文件系统往往采用分层结构实现,大概分为文件管理、目录管理和磁盘管理三层。

  1. 文件管理实现文件逻辑结构,为用户提供各种文件系统调用及文件访问权限的设置工作。
  2. 目录管理负责查找文件描述符,进而找到需要访问的文件,并进行访问权限检查等工作,还需要完成目录的添加、删除、重排等操作
  3. 磁盘管理除管理文件空间外,还将文件的逻辑地址转换为磁盘的物理地址,即由逻辑块号找到柱面号、磁头号与扇区号,设备与内存之间的数据传输操作由文件系统调用设备管理实现。

文件的目录结构中往往是具有双向索引结构的,如下图

文件控制块(File Control Block,FCB) *

  1. 文件控制块是操作系统为每个文件建立的唯一数据结构,包含了全部的文件属性。
  2. 目的是为方便操作系统对文件的管理、控制和存取。
  3. 文件由 FCB 和文件体组成,创建文件时,系统要同时创建 FCB。

文件目录

文件目录是实现文件的按名存取的关键数据结构,目录结构一般是层次性的、非线性的,多维坐标可以通过一定方式降成一维坐标。

文件目录需要永久保存,因此也组织成文件存放在磁盘上,称目录文件

  1. 需要时调入内存;
  2. 目录文件永不为空,至少包含当前目录 . 和父目录 ..

为了加快文件查找速度,通常将FCB 汇集和组织在一起形成文件目录,文件目录包含许多目录项,目录项分为两种,分别描述子目录和描述文件。

文件系统的基本功能之一就是负责文件目录的建立、维护和检索,要求编排的目录便于查找、防止冲突

Linux 系统的文件目录建立方法 *

Unix 系统中,文件的索引结构存放在 inode 节点中。

  1. FCB 中的文件名和其他管理信息分开,其他信息单独组成一个数据结构,成为索引节点 inode,此节点的位置由 inode 号标识。

  1. 这样目录项就仅剩下了文件名和 inode 号,称为基本目录项,一个磁盘块就可以放置更多的基本目录项
  2. inode 被集中存放在磁盘的 inode 区,和目录去是分割开的,按名存储是根据目录块进行的。
    1. inode 允许一个文件可以被多次访问。
    2. inode 不应该过多,类比图书馆卡片。
  3. 能够减少索引文件所需访问的磁盘物理块数。
  4. VFS 的 inode 的部分内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
struct inode {
unsigned long i_ino; /* inode 号 */
atomic_t i_counl; /* inode 引用数 */
kdev_t i_dev; /* inode 所在设备*/
loff_t i_size; /* inode 所在设备*/
nlink_t i_nlink; /* inode 所在设备*/
unsigned long i_blksize; /* inode 所在设备*/
unsigned long i_block; /* inode 所在设备*/
struct inode_operations * i_op; /* inode 所在设备*/
...
union {
struct minix_inode_info minix_i;
struct ext2_inode_infb ext2_i;
...
}
}
  1. 由于磁盘 inode 记录文件的属性和相关信息,会被频繁访问,我们在内存区开辟内存索引节点表,又称活动 inode 表,含 100 个表项,每个表项称为一个活动 inode
    1. 磁盘 inode 反应文件静态特性。
    2. 活动 inode 反应文件动态特性。
  2. 嵌入在 inode 中的索引地址表不可以太大,不然对于一个大文件而言,就会比较大,根据下面公式我们可以发现 inode 区相同情况下放置的 inode 号就会变少,导致可能陷入磁盘还有物理空间,但是没有 inode 号可以使用的尴尬境地。
    1. 文件较小使用直接地址(直接索引)
    2. 文件较大使用间接索引

\[ total_{inode} = \frac{inode 区容量}{inode 尺寸(尽量小)} \]

层次目录结构 *

一级目录结构

一级目录结构:在操作系统中构造一张线性表,与每个文件的相关属性占用一个目录项,构成了一级目录结构。

缺点:由于用户与文件众多,容易重名,不利记忆;文件共享。

二级目录结构

第一级为主文件目录,它用于管理所有用户文件目录,它的目录项登记了系统接受的用户的名字及该用户文件目录的地址。

第二级为用户的文件目录,它为该用户的每个文件保存一个登记栏,其内容与一级目录的目录项相同。

每一用户只允许查看自己的文件目录。

特点:

  1. 采用二级目录管理文件时,因为任何文件的存取都通过主文件目录,于是可以检查访问文件者的存取权限,避免一个用户未经授权就存取另一个用户的文件,使用户文件的私有性得到保证,实现了对文件的保密和保护
  2. 特别是不同用户具有同名文件时,由于各自有不同的用户文件目录而不会导致混乱
  3. 对于同一个用户而言,同样存在文件多、容易重名问题

树形目录结构

每一级目录可以登记下一级目录,也可以登记文件,从而,形成了层次文件目录结构

层次目录结构通常采用树形目录结构,它是一棵倒向的有根树,树根是根目录;

  1. 从根向下,每一个树分叉(树枝)是一个子目录
  2. 树叶是文件

不同类型的树形目录结构 *

  1. 纯树型目录结构:每个文件都只有一个父目录,缺点:文件的共享不是对称的,其他授权用户必须通过属主目录才能访问文件。
  2. 有向无环图则允许文件有多个父目录,破坏了树特性,但是不同用户可以用对称的方式实现文件共享,即可能属于不同用户的多个目录使用不同的文件名访问和共享同一个文件,维护复杂,需要维护文件的引用计数(用于文件删除)

不同操作系统的目录结构的实现 *

Linux 支持多父目录:

  1. 主父目录是文件拥有者,文件存放在该目录下。
  2. 次父目录通过 link 方式来链接和引用。
  3. 下图中便示例这种文件共享的情形,文件 /home/fei1myfile.c 的主父目录(图中实线表示),/home/fei2/home/fei3/fei4 均为文件 myfile.c 的次父目录(图中虚线表示)。

Windows 实现被称作“快捷方式”的多父目录连结,快捷方式是一些指向不同文件夹(子目录)和菜单之间任意复制和移动的文件及文件夹的指针,删除快捷方式就是删除指针。

树形目录结构的特点

  1. 较好地反映现实世界中具有层次关系的数据集合和较确切地反映系统内部文件的组织结构;
  2. 不同文件可以重名,只要它们不位于同一末端的子目录中;
  3. 易于规定不同层次或子树中文件的不同存取权限,便于文件的保护、保密和共享。

树形目录结构中的文件定位

  1. 在树形目录结构中,一个文件的全名包括从根目录开始到文件为止,通路上遇到的所有子目录路径,又称为路径名
  2. 各子目录名之间用正斜线/(反斜线\)隔开
  3. 一个硬盘分区可以组织成一颗子树
    1. 每棵子树可以对应于一个逻辑盘符(Win):最多有 26 个逻辑盘符
    2. 也可以把众多子树嫁接成一颗大树(UNIX)

文件目录的管理

  1. 输入包含路径的文件名(依据层次式的目录和结构解析)
  2. 在指定的时候目录块提取改文件的目录项

文件查找

每个目录在创建时都自动含有两个特殊目录项:

  1. .:目录自身的 inode 的入口
  2. ..:父目录的 inode 的入口

绝对路径与相对路径:

  1. 绝对路径是从根目录开始往下进行推导。
  2. 相对路径是从当前目录开始往下进行推导。

假设应用进程要打开文件 /home/feil/myfile.c,文件系统开始搜索

  1. 首先,遇到根目录 /,它通常被存放在磁盘的固定盘块中,根据活动 inode 表中根目录的活动 inode,把它作为当前工作索引节点并将其第一个物理块读入内存缓冲区
  2. 接着读入路径的第一个分量字符串 home;文件系统对根目录的内容进行搜索,若找不到,则依次读入第二、第三个物理块,...,进行比较,直至找到 home 的 inode 号
  3. 检查活动 inode 表
    1. 若找不到 home 的 inode,为其分配一个活动 inode,由于每个 inode 位于磁盘上已分配好的固定位置,可从磁盘 home 的 inoe 中装人其内容;
    2. 否则,直接查找 home 的活动 inode,通过属性查明 home 为子目录,经核对符合访问权限,把它作为当前工作索引节点,读人路径的第二个分量字符串 feil,子目录 home 对应的 inode 为 685,从目录文件第一个物理块中可找到子目录 feil 的 inode 为 270
  4. 类似地读入子目录 feil 目录文件的物理块便能找到 myfile.c 的 inode 号为 302;文件系统为此文件在活动 inode 表中分配一个活动 inode , 从 myfile.c 的磁盘 inode 中装入内容。中间任何一步出错都会返回错误码,由于路径名分析完毕,这时修改活动 inode 的有关内容,打开文件目录的查找操作到此结束。

现代操作系统都配置了更改工作目录的命令。

目录项查找

  1. 顺序查找法:一次扫描
  2. 二分查找法:目录表项是按键顺序编排
  3. 杂凑法:把每个文件名经过变换函数变为唯一的目录表项。

文件目录处理

树型目录结构存在的一个问题是:当一个文件经过许多目录节点时,使用很不方便;系统在沿路径查找目录时,往往要多次访问文件存储器,使访问速度大大减慢;

若把所有文件的目录都复制到主存,访问速度是加快了,但又增加了主存的开销;

一种有效办法是把常用和正在使用的那些文件目录复制进主存,这样,既不增加太多的主存开销,又可明显减少目录查找时间。

活动文件表

系统可以为每个用户进程建立一张活动文件表,当用户使用一个文件之前,先通过“打开”操作,把该文件有关目录信息复制到指定主存区域,有关信息填入活动文件表,以建立用户进程和该文件索引的联系。

当不再使用该文件时,使用“关闭”,切断用户进程和这个文件的联系;同时,若该目录已被修改过,则应更新辅存中对应的文件目录

文件系统功能及实现

  1. 文件系统向应用程序提供了一组系统调用,包括建立、打开、关闭、撤销、读/写和控制,通过这些系统调用,用户能够获得文件系统的各种服务。
  2. 系统会为每一个用户进程建立一张打开文件表
    1. 用户使用文件之前先通过打开操作,将文件 FCB 拷贝到指定内存位置
    2. 当不在使用时,通过关闭操作切断和文件的联系,释放文件的 FCB。
  3. 接下来以 Linux 系统为例,介绍其文件系统调用的种类、功能和实现。内核将磁盘作为主要文件存储器,磁盘按扇区编号,扇区序列分成三个部分。
  4. 文件系统内部结构如下图所示:不是三级坐标,是经过转化后的结构

扇区序列划分

引导块:0 号块

超级块:1 号块

  1. 存放文件系统结构和管理信息,如记录 inode 表所占盘块数、文件数据所占盘块数、主存中登记的空闲盘块数、主存中登记的空闲块物理块号、主存中登记的空闲 inode 数、主存中登记的空闲 inode 编号,及其他文件管理控制信息,
  2. 可见超级块既有盘位示图的功能,又记录整个文件卷的控制数据
  3. 每当一个块设备作为文件卷
    1. 被安装时,该设备的超级块就要复制到主存系统区中备用
    2. 拆卸文件卷时,修改过的超级块需复制回磁盘的超级块中。

磁盘 inode(索引节点)区:2-(k+1) 块

  1. 一共 k 个块,k 不确定,在磁盘分区的时候确定
  2. 存放 inode 表,每个文件都有各种属性,它们被记录在称为索引节点 inode 的结构中;所有 inode 都有相同大小,且 inode 表是 inode 结构的列表,文件系统中的每个文件在该表中都有一个 inode。
  3. 又分磁盘 inode 表和主存活动 inode 表,后者解决频繁访问磁盘 inode 表的效率问题。

磁盘信息(数据)区:(k+2) 及以后

目录块和数据块(目录文件和数据文件的区别):

  1. 文件的内容保存在这个区域,磁盘上所有物理块的大小是一样的
  2. 如果文件包含超过一块的数据,则文件内容会存放在多个盘块中。

文件系统磁盘结构

  1. 用户打开文件表:进程的 PCB 结构中保留一个 files_struct,称为用户打开文件表或文件描述符表
    1. 表项的序号为文件描述符 fd
    2. 该登记项内登记系统打开文件表的一个入口指针 fp
    3. 通过此系统打开文件表项连接到打开文件的活动 inode
  2. 系统打开文件表:是为解决多用户进程共享文件、父子进程共享文件而设置的系统数据结构 file_struct
    1. 一个文件可能被多个进程同时打开或打开多次,导致位移量不同。
    2. 每次打开就是一个 file,多次打开就是多个 file。
    3. 一个 inode 可以连接 0 个或多个 file,多个 file 对应一个 inode。
    4. 内核内存区开辟最多存放 256 项的系统打开表区。
  3. 主存活动 inode 表:为解决频繁访问磁盘索引节点 inode 表的效率问题,系统开辟的主存区,正在使用的文件的 inode 被调入主存活动索引节点 inode 中,以加快文件访问速度。

文件相关操作

文件的使用

  1. 用户通过两类接口与文件系统联系
  2. 第一类是与文件有关的操作命令,例如,UNIX 中的 cat,cd,cp,find,mv,rm,mkdir,rmdir 等等
  3. 第二类是提供给用户程序使用的文件类系统调用,基本文件类系统调用有:建立、打开、读/写、定位、关闭、撤销

创建文件

1
2
3
4
int fd;           // 创建成功后系统返回的文件描述符
int mode; // mode 是文件所具有的权限
char *filenamep; // 指向要创建的文件路径名的字符串指针
fd = create(filenamep, mode);
  1. 创建成功后,存取权限存放在 inode 的 i_mode 中。
  2. fd 是创建成功后系统返回的文件描述符,即用户打开文件表中相应文件表项的序号。
  3. create() 创建的同时也打开了文件。
  4. 创建过程:create("path", 0775)
    1. 为新文件 newfile 分配磁盘 inode 和活动 inode,并把 inode 编号与文件分量名 newfile 组成新目录项,记到目录中,这个过程中执行目录检索程序。
    2. 在新文件所对应的活动 inode 中置初值,如置存取权限 i_mode=0775,连接计数 i_nlink=1 等。
    3. 分配用户打开文件表项系统打开文件表项,为后者置初值,包括特征位为写,读写位移 f_offset 清 0。
    4. 把各表项及文件对应的活动 inode 用指针连接起来
    5. 把文件描述字 fd 返回给调用者。

文件的删除

  1. 删除把指定文件从所在的目录文件中除去。
  2. 如果没有连接用户(i_link 为 1),还要把文件占用的存储空间释放。删除系统调用形式为:unlink(filenamep)
  3. 在执行删除时,必须要求用户对该文件具有""操作权。

文件的打开

1
2
3
int fd, mode;
char * filenamep;
fd = open(filenamep, mode);
  1. 文件使用前需要打开,以建立进程与文件之间的联系,而文件描述符唯一标识了这种连接,其任务是把文件的磁盘 inode 复制到内存活动 inode中去,同时建立一个独立的读写文件数据结构,即系统打开文件表的一个表项。
  2. 打开过程:
    1. 检索目录
      1. 如果没有则会出错
      2. 检索到指定文件后,把它的磁盘 inode 复制到活动 inode 表中。
      3. 如果 inode 号已经在活动表项中则直接执行下一步。
    2. 根据参数 mode 核对权限(与创建时的 mode)
      1. 如果非法,则这次打开失败。
      2. 当“打开”合法时,为文件分配用户打开文件表项系统打开文件表项,并为后者赋初值。通过指针建立这些表项与活动 inode 间的联系。把文件描述字,即用户打开文件表中相应文件表项的序号返回给调用者。
  3. 输入是含路径的文件名 \(\rightarrow\) 依据层次式目录结构解释与检索 \(\rightarrow\) 匹配文件名并读取目录项 \(\rightarrow\) 提取 inode 号 \(\rightarrow\) 按号定位,在 inode 区读取 inode 数据结构(主存活动 inode)
  4. 系统实现上必须有 inode 号,但是对文件名而言是透明的。

文件的关闭

1
2
int fd;
close(fd);
  1. 关闭文件时需要释放掉 inode 来保证空间。
  2. 关闭过程
    1. 根据 fd 找到用户打开文件表项,再找到系统打开文件表项。释放用户打开文件表项
    2. 把对应系统打开文件表项中的 f_count 减 1,如果非 0,说明还有进程共享这一表项,不用释放直接返回;否则释放表项。
    3. 把活动索引节点中的 i_count 减 1,若不为 0,表明还有用户进程正在使用该文件,不用释放而直接返回,否则在把该活动索引节点中的内容复制回文件卷上的相应索引节点中后,释放该活动索引节点。
  3. f_count 和 i_count 分别反映进程动态地共享一个文件的两种方式
    1. f_count 反映不同进程通过同一个系统打开文件表项共享一个文件的情况;
    2. i_count 反映不同进程通过不同系统打开文件表项共享一个文件的情况。
  4. 通过两种方式,进程之间既可用相同的位移指针 f_offset,也可用不同位移指针 f_offset 共享同一个文件。

读文件

1
2
3
4
5
int nr;     // 系统调用后实际读入的字节数
int fd; // 文件描述符
int count; // 要求传送的字符
char buf[]; // 应该输入的用户数据区的首地址
nr = read(fd, buf, count);
  1. 读指将文件的内容读入用户数据区,读入数据的逻辑地址由 offset 决定
  2. 读文件过程
    1. 系统根据 f_flag 中的信息,检查读操作合法性
    2. 如果合法,再根据当前位移量 f_offset 值,要求读出的字节数,及活动索引节点中 i_addr 指出的文件物理块存放地址,把相应的物理块读到缓冲区中,然后再送到 buf 指向的用户主存区中。

写文件

1
2
3
4
5
int nw;     // 系统调用后实际写入的字节数
int fd; // 文件描述符
int count; // 要求传送的字符
char buf[]; // 数据传送的源地址
nw = write(fd, buf, count);

写是将用户数据区的数据写入文件中,写入数据的逻辑地址由 offset 决定

文件的随机存取

  1. 在文件初次“打开”时,文件的位移量 f_offset 清空为 0,以后的文件读写操作总是根据 offset 的当前值,顺序地读写文件。为了支持文件的随机访问,提供系统调用 lseek,它允许用户在读、写文件前,事先改变 f_offset 的指向系统调用的形式为:
1
2
3
4
long offset;      // 当前的 offset
int whence; //
int fd; // 指向一个以读或写方式打开的文档
lseek(fd, offset, whence);
  1. 文件描述字 fd 必须指向一个用读或写方式打开的文件
    1. 当 whence 是 0 时,则 f_offset 被置为 offset,
    2. 当 whence 是 1 时,则 f_offset 被置为文件当前位置加上 offset。

文件的安全与保护

文件是计算机系统的重要资源,因此,要求文件系统具有保障文件安全的手段,提供文件保密的措施,有效地实现文件的共享。

  1. 文件共享是指不同用户共同使用某些文件;
  2. 文件保护是指防止文件被破坏;
  3. 文件保密则是指防止文件及其内容被其他用户窃取。

文件共享

文件共享是计算机用户完成共同任务所必需的

文件共享带来许多好处,如:

  1. 减少用户大量重复性劳动;
  2. 免除系统复制文件的工作;
  3. 节省文件占用的存储空间;
  4. 减少程序设计输入输出文件的次数。

文件共享的并发控制

在允许文件共享的系统中,操作系统应提供手段实现对共享文件的同步控制

多个进程可能同时存取一个文件,如果它们同时进行读操作,操作系统应对文件进行公用控制。

如果有进程进行写操作,例如,有两个进程,进程 A 要求修改文件,同时进程 B 要求读出同一文件中的数据,则操作系统必须提供同步控制机制,以保证文件数据的完整性。

文件的保密措施

文件保密是指文件及其内容不能被未经文件主授权的其他用户窃取。

文件的保密措施有以下几种:

  1. 隐蔽文件目录
  2. 设置口令
  3. 使用密码:避免高级技能用户直接访问磁盘数据

文件的保护

文件保护是指防止文件被破坏。

操作系统必须提供文件保护机制,有效实现文件的完整性。

常用的文件保护办法:

  1. 文件副本
  2. 文件存取矩阵与文件存取表
  3. 文件属性

文件的副本

文件系统必须要有防止硬软件故障,保存信息完整性的能力。

文件副本是主要实现机制:

  1. 动态多副本技术
  2. 转储、备份与恢复

动态多副本

第一种办法是在多个介质上维持同一内容的文件,并且在更新内容时同时进行;

这种方法需要增加设备费用和系统负载一般适用于容量较小且较为重要的文件,例如不需更新的系统文件及专用文件,当文件发生故障时只要切换到备用设备就可。

文件转储

文件转储:定时把文件复制转储到其它介质上,当某介质上出现故障时,复原转储文件。

转储又可分成两种方式:

  1. 一是在一定时间间隔或一个单位处理结束时,系统自动复写更新过的文件和数据;
  2. 二是每天或每周把文件信息全部复写一遍,需要时再通过装入转储文件来恢复系统,诸如 BACKUP、RESTORE 等命令。

文件的存取控制矩阵

  1. 系统为每个用户设置访问每个文件对象的存取属性
  2. 系统的全部用户对全部文件的存取属性就组成的一个二维矩阵,称为存取控制矩阵

\[ \begin{bmatrix} a_{11} & a_{12} & ... & a_{1n} \\ a_{21} & a_{22} & ... & a_{2n} \\ . & . & ... & . \\ a_{n1} & a_{n2} & ... & a_{nn} \\ \end{bmatrix} \]

存取控制表

  1. 由于操作系统拥有很多用户和众多文件,存取控制矩阵是一个稀疏矩阵,可以将其简化为一张存取控制表
  2. 每行包括:用户、文件、存取属性
  3. 存取控制表仅登记那些对文件拥有存取属性的部分

基于存取控制矩阵/表的文件保护

  1. 存取属性:可以有访问、读、写、执行、创建、删除、授权等等
  2. 系统通过查阅(矩阵/表)核对用户对文件的存取权限
  3. 文件属主使用 GRANT、REVOKE 等命令进行授权,甚至把授权权转授给他信任的用户
  4. 系统管理用户(超级用户)等同于文件属主权限,并获得对系统文件的授访问权权限

文件属性

文件属性是指操作系统为文件配置的控制和管理信息,目的是为了方便和用户对文件的管理、保护和使用。

文件属性的内容

  1. 文件基本属性:文件名和扩展名、文件属主 ID,文件所属组 ID 等
  2. 文件类型属性:普通文件等
  3. 文件保护属性:规定谁可以访问,以何种方式访问,常见的文件访问方式有读、写、执行、更新、删除等,有的系统还为文件设置口令保护。
  4. 文件管理属性:如创建时间、最后访问时间、最后修改时间等。
  5. 文件控制属性:
    1. 文件逻辑结构信息,如记录键、记录类型、记录个数、记录长度、成组因子数等。
    2. 文件物理结构信息,如文件所在设备名、物理设备类型、记录存放的盘块号或文件信息首块盘块号。
  6. 存取控制表的一种简化方法是用户分类,再针对每类用户规定文件属性。

文件属性的例

执行
文件主 1 1 0
伙伴 1 0 0
其他用户 1 0 0
  1. chmod 命令可以改变文件属性
  2. chown 命令用于变更文件属主
  3. chgrp 命令用于变更用户伙伴

文件存取方法

  1. 文件存取方法是操作系统为用户程序提供的使用文件的技术和手段(读写文件存储器上的物理记录的方法)
  2. 文件存取方法在某种程度上依赖于文件的物理结构
  3. 文件系统应该尽可能提供多种存储方法,比如索引文件可以模拟顺序存取、一定程度上的直接存取

顺序存取

  1. 记录顺序进行读/写操作的存取方法称顺序存取
  2. 过程:
    1. 读操作根据读指针读出当前记录,同时推进读指针,指向下一次要读出的记录
    2. 写操作则设置写指针,把一个记录写到文件未端, 同时推进写指针
  3. 允许对读指针进行前跳或后退 n(整数)个记录的操作(允许对固定长度记录的顺序文件采用随机访问)
  4. 顺序访问主要用于磁带文件,也适用于磁盘上的顺序文件。

直接存取(随机存取)

  1. 可以非顺序地从文件中的任何位置存取文件内容。
  2. 很多应用场合要求快速地以任意次序直接读写某个记录,例如,航空订票系统,用航班号作标识,把特定航班的所有信息存放在物理块中,用户预订某航班时,直接计算出该航班的存位置
  3. 常用于磁盘文件。

索引存取

  1. 基于索引文件的索引存取方法
  2. 文件的记录不按位置而是按其记录名和记录键来编址,所以用户提供记录名或记录键之后,先按名查找,在查找需要的记录。
    1. 采用记录键时,往往按照一种次序如字母序进行顺序存放
    2. 除可采用按键存取外,也可以采用顺序存取或直接存取的方法
  3. 实际的系统中,大都采用多级索引,以加速记录查找过程

文件的使用

  • 用户通过两类接口与文件系统联系
  • 第一类是与文件有关的操作命令,例如,UNIX 中的 cat,cd,cp,find,mv,rm,mkdir,rmdir 等等
  • 第二类是提供给用户程序使用的文件类系统调用,基本文件类系统调用有:建立、打开、读/写、定位、关闭、撤销

建立文件

“建立文件”用于创建一个文件。

所需参数:文件名、设备类(号)、文件属性及存取控制信息。

处理流程:在相应设备上建立一个文件目录项,为文件分配第一个物理块,在活动文件表中申请一个项,登记有关目录信息,并返回一个文件句柄。

撤销文件

“撤销文件”用于删除一个文件。

所需参数:文件名和设备类(号)。

处理流程:若文件没有关闭,先关闭文件;若为共享文件,进行联访处理;在目录文件中删去相应目录项;释放文件占用的文件存储空间。

打开文件

“打开文件”用于建立起文件和用户进程之间的使用联系。

所需参数:文件名、设备类(号)、打开方式。

处理流程:在主存活动文件表中申请一个项,返回一个文件句柄;跟据文件名查找目录文件,把目录信息复制到活动文件表相应栏;按存取控制说明检查访问的合法性;若打开的是共享文件,则应有相应处理。

关闭文件

“关闭文件”用于结束一个文件的读写。

所需参数:文件句柄。

处理流程:将活动文件表中该文件的“当前使用用户数”减 1;若此值为 0,则收回此活动文件表;完成“推迟写”;若活动文件表目内容已被改过,则应先将表目内容写回文件存储器上相应表目中,以使文件目录保持最新状态。

读/写文件

“读/写文件”用于读写文件。

所需参数:文件句柄、用户数据区地址、读写的记录或字节个数。

处理流程:按文件句柄从活动文件表中找到该文件的目录项信息;根据目录项指出的该文件的逻辑和物理组织方式,把相关逻辑记录转换成物理块。

定位文件

“定位文件”用于调整所打开文件的读写指针位置。

所需参数:文件句柄,定位指针。

文件共享

  1. 文件共享指不同进程共同使用同一个文件,文件共享为不同进程完成共同任务所需。
  2. 节省大量外存空间,减少因文件复制而增加的 I/O 操作次数。

静态共享

  1. 允许一个文件同时属于多个目录,但是实际上文件仅有一处物理存储。
  2. 文件链接:从多个目录可到达文件的链接。
  3. 无论进程是否运行,文件链接关系都存在,所以称为静态共享。
  4. 链接的文件的存在形式:
    1. 同一父目录下的不同文件名出现
    2. 不同父目录下的相同或不同文件名出现
1
2
3
char* oldnamep;// 指向已存在文件名的字符串的指针
char* newnamep;// 指向文件别名的字符串的指针
link(oldnamep, newnamep);
  1. 执行步骤
    1. 检索目录找到 oldnamep 所指向文件的索引节点 inode 编号。
    2. 再次检索目录找到 newnamep 所指文件的父目录文件,并把已存在文
    3. 的索引节点 inode 编号与别名构成一个目录项,记入到该目录中去。
    4. 把已存在文件索引节点 inode 的连接计数 i_nlink 加 1。
  2. 链接实际上是共享已存在文件的索引节点 inode,完成链接的系统调用
    1. link("/home/fei1/myfile.c","/home/fei2/myfile.c")
    2. link("/home/fei1/myfile.c","/home/fei3/fei4/testfile.c");
  3. 执行后,三个路径名指的是同一个文件:
    1. /home/fei1/myfile.c
    2. /home/fei2/myfile.c
    3. /home/fei3/fei4/testfile.c
  4. 文件解除链接调用形式为:unlink(namep),解除链接与文件删除执行的是同一系统调用代码
    1. 删除文件是从文件主角度讲的
    2. 解除文件连接是从共享文件的其他用户角度讲的
  5. 都要删去目录项,把 i_nlink 减 1,不过,只有当 i_nlink 减为 0 时,才真正删除文件。

动态共享

  1. 文件动态共享是系统中不同的用户进程或同一用户的不同进程并发访问同一文件。
  2. 这种共享关系只有当用户进程存在时才可能出现,一旦用户的进程消亡,其共享关系也就自动消失。
  3. 文件的每次读写由一个读/写位移指针指出要读写的位置。现在的问题是:应让多个进程共用同一个读/写位移,还是各个进程具有各自的读写位移呢?

使用同一位移指针的文件共享

  1. 同一用户父、子进程协同完成任务,使用同一读/写位移,同步地对文件进行操作。
  2. 该位移指针宜放在相应文件的活动 inode 中。当用系统调用 fork()立子进程时,父进程的 PCB 结构被复制到子进程的 PCB 结构中,使两个进程的打开文件表指向同一活动的索引节点,达到共享同一位移指针的目的。

  1. 注意 f_count = 2 表示共享

使用不同位移指针的文件共享

  1. 多用户进程共享文件,每个希望独立地读、写文件,这时不能只设置一个读写位移指针,须为每个用户进程分别设置一个读、写位移指针
  2. 位移指针应放在每个进程用户打开文件表的表目中。
  3. 这样,当一个进程读、写文件,并修改位移指针时,另一个进程的位移指针不会随之改变,从而,使两个进程能独立地访问同一文件,会新建系统打开文件表(包含 f_offset)

两种方式存在的问题

  1. 问题:读写位移指针的位置设置和数目是不同的。
  2. 解决:系统建立系统打开文件表,包含读写位移指针 f_offset、文件访问计数 f_count、读写标志 f_flags、指向活动索引节点的指针 f_inode

两种方式的实现

  1. 使用同一位移指针的文件共享:先打开文件,再 fork()
  2. 使用不同位移指针的文件共享:先 fork(),再打开文件

符号链接共享

  1. 操作系统可支持多个物理磁盘或多个逻辑磁盘(分区),那么,文件系统是建立一棵目录树还是多棵目录树呢?
    1. 盘符或卷标分配给磁盘或分区,并将其名字作为文件路径名的一部分,比如 Windows
    2. 每个分区有自己的文件目录树,当有多个文件系统时,可通过安装的办法整合成一棵更大的文件目录树,如 UNIX/Linux
  2. 问题:系统中每个文件对应一个 inode,编号是唯一的,但两个不同的磁盘或分区都含有相同 inode号对应的文件,也就是说,整合的目录树中,inode 号并不唯一地标识一个文件,
  3. 办法:拒绝创建跨越文件系统的硬链接。

硬链接

将文件名和自身 inode 链接起来,只能用于单文件系统,可以文件共享,但是不能目录共享。

软连接(符号链接)

  1. 符号链接又称软链接,是一种只有文件名,不指向 inode 的文件,通过名称引用文件。
  2. 符号链接共享文件的实现思想:用户 A 目录中形式为 afile \(\rightarrow\)bfile,实现 A 的目录与 B 的文件的链接。其中只包含被链接文件 bfile 的路径名而不是它的 inode 号,而文件的拥有者才具有指向 inode 的指针
  3. 当用户 A 要访问被符号链接的用户 B 的文件 bfile,且要读“符号链接”类文件时,被操作系统截获,它将依据符号链接中的路径名去读文件,于是就能实现用户 A 使用文件名 afile 对用户 B 的文件 bfile 的共享。
    1. 优点:能用于链接计算机系统中不同文件系统中的文件,可链接计算机网络中不同机器上的文件,此时,仅需提供文件所在机器地址和该机器中文件的路径名。
    2. 缺点:搜索文件路径开销大,需要额外的空间查找存储路径

辅存空间管理

磁盘等大容量辅存空间被 OS 及许多用户共享,用户进程运行期间常常要建立和删除文件,OS 应能自动管理和控制辅存空间。

随着用户文件不断建立和撤销,文件存储空间会出现许多“碎片”。

OS 解决“碎片”的办法是整理“碎片”;在整理过程中,往往对文件重新组织,让其存放在连续存储区中。

辅存空间的分配方式

连续分配:文件存放在辅存空间连续存储区中。在建立文件时,用户必须给出文件大小,然后,查找到能满足的连续存储区供使用。优点是顺序访问时速度快,管理较为简单,但为了获得足够大的连续存储区,需定时进行“碎片”整理

非连续分配:

  1. 一种方法是以块(扇区)为单位,扇区不一定要连续,同一文件的扇区按文件记录的逻辑次序用链指针连接或位示图指示;
  2. 另一种方法是以为单位,簇是由若干个连续扇区组成的分配单位;实质上是连续分配和非连续分配的结合。各个簇可以用链指针、索引表,位示图来管理。
  3. 优点是辅存空间管理效率高,便于文件动态增长和收缩。

空闲块的管理:位示图

磁盘空间通常使用固定大小的块,可方便地用位示图管理,用若干字节构成一张位示图,其中每一字位对应一个物理块,字位的次序与块的相对次序一致,字位为‘1’表示相应块已占用,字位为‘0’表示该块空闲。

微型机操作系统 VM/SP、Windows 和 Macintosh 等操作系统均使用这种技术管理文件存储空间。

主要优点是:

  1. 每个盘块仅需 1 个附加位,如盘块长 1KB,位示图开销仅占 0.012%
  2. 可把位示图全部或大部分保存在主存,再配合现代机器都具有的位操作指令,实现高速物理块分配和去配。

空闲块的管理:空闲区表 *

  1. 该方法常用于连续文件,将空闲存储块的位置及其连续空闲的块数构成一张表。
  2. 分配时,系统依次扫描空闲区表,寻找合适的空闲块并修改登记项;
  3. 删除文件释放空闲区时,把空闲区位置及连续的空闲区长度填入空闲区表,出现邻接的空闲区时,还需执行合并操作并修改登记项。
  4. 空闲区表的搜索算法有首次适应、邻近适应、最佳适应和最坏适应算法等。

空闲块的管理:空闲块成组连接法 *

  1. 把所有空闲块连接在一起,系统保持指针指向第一个空闲块,每一空闲块中包含指向下一空闲块的指针
  2. 申请一块时,从链头取一块并修改系统指针;
  3. 删除时释放占用块,使其成为空闲块并将它挂到空闲链上。
  4. 这种方法效率低,每申请一块都要读出空闲块并取得指针,申请多块时要多次读盘,但便于文件动态增长和收缩

空闲块的管理:空闲块列表 *

把所有空闲块物理地址放到一个空闲块列表文件中,由于它非常庞大,不可能全部保存在内存中,有两种有效技术可以把该列表的一小部分保存在内存中:

  1. 列表用一个下推栈实现,栈中靠前数千个元素保留在内存专用区中。当分配一个新空闲块时,从栈顶弹出;当一个物理块被解除分配时,它被压入内存专用区的栈尾中。只有当下推栈中在内存的部分满或者空时,才需要在内存和磁盘之间进行传送。因此,该技术在大多数时候都提供了零时间的访问。
  2. 列表用一个 FIFO 队列实现,队列头和队列尾的几千项放在内存专用区中。分配空闲块时从队列头取出首项,取消分配时可以把它添加在内存专用区队列尾。只有当内存中的队列头部空或者内存中的队列尾部满时,才需要在磁盘和内存之间进行传送。

如上两个策略,可以用后台线程来完成排序。

空闲块的管理:空闲块成组连接法

  1. 图 6-13 给出 Linux 系统所采用的空闲块成组链接法。磁盘物理块长为 1024B。为了方便讨论,假定文件卷启用时共有可用空闲块 338 块,目前空闲块分成 4 组,39 块空闲块已在内存专用块中,剩余每 100 块划分成一组,每组中第一块(图中盘块号为 50、68 和 188)登记下一组空闲盘块号和空闲块总数。需要注意,在最后一组中,第 1 项是 0,作为结束标志,表明系统空闲盘块链已经结束。
  2. 操作系统启动时,将磁盘专用块复制到内存系统工作区中,访问内存专用块就可完成申请或释放空闲盘块的操作。
  3. 分配空闲磁盘块时,总是先把专用块中的空闲块计数减 1,以它为指针找到专用块的相应表项,其内容就是要分配的空闲磁盘块号。
  4. 当空闲块计数减 1 后等于 0 时,专用块中仅剩 1 个磁盘块号,此时要取出表项中的磁盘块号(设为 i),再把此盘块中所保存的下一组空闲磁盘块链接信息经缓冲区复制到内存专用块中,然后把当前磁盘块分配出去。
  5. 释放存储块时,将磁盘块号记录在由专用块所指示的表项中,然后空闲块计数加 1。若发现此表已满(达 100 项),则应把整个表的内容经缓冲区复制到下面要释放的磁盘块中,然后将释放块的块号写入专用块中的第一个位置,置空闲块计数为 1。
  6. 搜索到磁盘块中的第 1 项是 0 时,系统应向操作员发出警告,表明空闲块已经用完。
  7. 需要注意,开始时空闲块是按序排列的,操作系统经过一段时间运行,文件系统中的空闲块号未必能保持连续,但只要符合分组及组间连接的原则,空闲块可按任意次序排列。事实上,经过若干次分配和释放操作后,空闲块物理块号必定不再按序排列。

文件系统的实现层次

补充:内存映射文件 *

  1. 内存映射文件的原理如下:把进程需要访问的文件映射到其虚地址空间中,于是便可通过读写这段虚地址进行文件访问,而磁盘访问转变成内存访问。也就是说,把磁盘中的文件视为进程的虚地址的一部分, 故也称映射文件 I / O 。内存映射文件是按照文件名来访问的,多个进程可同时把同一个文件映射到各自的虚地址空间中,且虚地址不必相同。随着进程的运行,被引用的映射文件由存储管理程序装人内存,多个进程读写虚存的映射文件区就可以共享文件信息。其优点是方便易用,节省空间,便于共享,利于通信。
  2. 详见 P326

补充:文件系统的性能与可靠性 *

详见 P330

文件系统性能问题措施

  1. 盘块高速缓存:局部性原理;写回优化
  2. 数据预先读入:仅适用于顺序访问
  3. 信息优化分布:磁盘上的信息优化分布
  4. 磁盘驱动调度:不同驱动调度算法
  5. 内存映射文件:将内存访问转换为内存访问,将想要访问的文件映射到进程的虚存空间,特别适用于文件共享场景。

提高文件可靠性措施

  1. 磁盘坏块管理:软硬件解决方案
  2. 备份数据:完全、增量和更新备份

文件系统一致性检查

  1. 磁盘块一致性检查:磁盘块要么占用要么空闲
  2. 文件一致性检查:关注 inode,出现无法释放等问题