文件系统

文件管理

⭐ 中优先级

本节的重点在于外存空间管理的方法,其他几个知识点也偶有考察,稍微了解下概念就行。

功能

文件系统(File System )作为操作系统与存储设备之间的桥梁,负责数据的存储、访问、管理和保护。简单来说,文件系统主要包含以下功能:

  1. 数据存储与组织
  • 文件系统以 文件目录 的形式组织数据,将存储设备的物理空间划分为 逻辑单元 (如文件、文件夹),便于用户和应用程序访问与管理数据。

    1. 空间管理
  • 通过 空闲块管理 (分配、回收、组织),文件系统高效利用存储空间,减少碎片,支持文件的创建、扩展和删除。常见方法包括 连续分配链接分配索引分配

    1. 数据访问与操作
  • 提供标准接口(如 打开关闭 )支持对文件的访问和操作,确保数据的高效检索和修改,同时支持 随机访问顺序访问

    1. 数据保护和安全
  • 权限管理

  • 数据完整性校验

注意

文件系统和磁盘的功能区别

文件系统和磁盘在存储管理中扮演不同角色。磁盘负责物理存储,提供固定大小的 扇区 (通常为 512字节4KB ),作为数据读写的 最小物理单位 。文件系统则在磁盘之上构建 逻辑结构 ,负责数据的组织和管理,以 盘块(或簇) 为单位进行空间分配和操作。

盘块/簇是文件系统定义的 逻辑单位 ,其大小在格式化时确定(常见如 4KB8KB 等),用于管理文件的存储和访问。盘块通常是 扇区 的整数倍,便于将逻辑操作映射到物理存储。扇区 则是磁盘的物理单位,硬件层面的最小读写单位,固定且不可更改。

全局结构

如上图所示,磁盘从逻辑上分为如下部分:

  1. 引导区 (Master Boot Sector,MBR ):引导区位于磁盘的起始位置,通常是磁盘的第一个 扇区 。它包含 引导加载程序 (boot loader),用于引导操作系统。引导加载程序负责启动计算机并加载操作系统内核。
  2. 分区表 (Partition Table):分区表通常存储在磁盘的第一个扇区之后,用于记录磁盘上的 分区信息 。分区表指示了磁盘上每个分区的起始位置、大小和文件系统类型。不同操作系统使用不同的分区表格式,如 MBR(Master Boot Record)和 GPT(GUID Partition Table)。
  3. 分区 (Partition):分区中存储有 文件系统 ,文件系统中包含 元数据数据区 这两个部分。
  • 元数据
    • 超级块 (Superblock):包含文件系统的关键信息,在计算机启动时,超级块会被载入内存。超级块中包含的典型信息包括分区的块的数量、块的大小、空闲空间的管理方式等。
    • 空闲块信息 :管理磁盘中空闲块的存储数据,具体方法见下文空闲空间管理方法
    • inodes :管理文件的元数据
  • 数据区 :文件系统的 数据区 存储了实际的文件数据。这是存储文件内容的地方。文件系统会将文件数据分为一个或多个 ,并将这些块分布在磁盘上的不同位置。文件系统的 数据区 通常占据了磁盘上的大部分空间。

下图是一个 文件系统分区 (Partition)上的存储示例,文件系统的 元数据superblockinode 位图区 (inode bmap)、数据块位图区 (data bmap)、inode 存储区 (inode region)这四个部分构成。

外存空闲管理

文件存储设备(如硬盘、SSD)将存储空间划分为多个大小相同的 物理块 (通常为 512字节4KB 或更大),以块为单位进行数据的读写和交换。因此,文件系统的外存管理实质上是对这些 物理块 (特别是 空闲块 )的组织、分配与回收的管理。以下详细说明空闲块管理的关键问题和方法:

空闲表法

再该方法中,系统需要维护一张 空闲块表 ,用以记录磁盘上尚未分配的连续空闲块的所在位置和大小。表格的每一行描述一个空闲区段。

空闲块表应包含以下两个字段:

  • 起始空闲盘块号 :该空闲区段的第一个盘块编号
  • 空闲盘块数 :该区段中连续空闲盘块的数量

这样,空闲块表就能够清晰、完整地反映磁盘空间的空闲情况,为后续的块分配和回收提供可靠依据。

空闲链表法

在本方法中,采用 链表 结构来组织和管理磁盘上的空闲数据块。链表的每个节点对应一个空闲块,并在节点中记录该块所在的磁盘块号(或块标识)。链表的头节点保存第一个空闲块的位置,随后每个节点的 next 指针指向 下一个空闲块 ,形成一条从头到尾依次链接的空闲块序列。

这样,所有空闲块就被构建成一条有序的链表:

  • 分配时 :系统只需从链表头部取出一个节点,即可得到一个可用的磁盘块;随后将头指针移动到下一个节点,完成快速分配。
  • 回收时 :释放的磁盘块会被重新包装成一个节点,插入到链表的适当位置(常见做法是插入链表头),从而实现 O(1) 的回收操作。
  • 遍历和合并 :在需要对空闲块进行合并或统计时,只需顺序遍历链表即可,所有空闲块的位置信息都已在节点中明确记录,避免了额外的查找开销。

因此,使用链表来管理空闲块既能保证在高频的分配/回收场景下保持低时间复杂度,又能通过一次遍历轻松实现空闲空间的统计与碎片整理,提升整体存储系统的效率和可靠性。

位图法

位图 (Bitmap)是一种用二进制位数组来管理磁盘块的技术。位图中的每一位(bit)对应磁盘上一个固定大小的数据块(通常为 4 KB、8 KB 等),通过该位的取值即可快速判断该块的使用状态。

  • 0 :对应的数据块为空闲块,意味着它尚未被分配,可以用于存放新文件的数据。
  • 1 :对应的数据块已被占用,已经分配给某个文件,不能再被其他文件使用。

位图 使用流程

  1. 初始化 :在文件系统创建时为整个磁盘块集合生成位图,初始全部置为 0(空闲)。
  2. 分配块 :当文件需要写入数据时,系统在位图中搜索第一个 0 位,找到后将该位改为 1,并返回对应的块号给文件系统。
  3. 回收块 :文件被删除或其数据块被释放时,系统把对应的位恢复为 0,表示该块重新进入空闲池。
  4. 持久化 :位图通常被写入磁盘的固定位置(例如超级块或专门的位图块),以保证系统重启后仍能恢复块的使用状态。

成组链接法

成组链接法 的实现细节相对繁琐,这里只要求掌握其核心思想(在选择题中出现的概率较低,但仍值得了解)。

· · · · ·

· · · · ·

其基本思路与文件混合索引分配方式相似:使用一个磁盘块来保存若干空闲盘块号 ,并通过链表把这些块组织起来。具体做法如下:

  1. 建立第一个空闲块组
  • 选取一个磁盘块 A 作为“空闲块组”。
  • A 中依次记录一定数量(如 10 ~ 20)个空闲盘块的盘号。
  • A 中的记录已满时,说明当前组已经没有预留的空闲盘号。
  1. 扩展空闲块组
  • 为了继续记录后续的空闲盘块,需要再分配一个新的磁盘块 B
  • B 同样用来保存若干空闲盘号。
  • 为实现组之间的连接,在 B 中的某个位置(通常是第一个记录位)存放 A 的盘块号,这个盘号充当“一阶间址”,即指向前一组的头结点。
  • 同时,A 需要保存 B 的盘块号,以便在遍历空闲块链时能够顺利跳到下一组。
  1. 空闲块的分配与回收
  • 当需要分配空闲盘块时,直接从当前组(如 A )的记录列表中取出一个盘号即可。
  • 如果取完后该组的记录为空,则将指向下一组 B 的指针提升为新的当前组,继续从 B 中取号。
  • 回收空闲盘块时,只需把盘号重新写入当前组的记录列表;若当前组已满,则按上述方式再申请一个新组并把该盘号写入新组的首位。

成组链接法通过“块内多址+块间链表”的组合方式,兼顾了存储密度和访问效率,是一种在文件系统中常用的空闲空间管理策略。

虚拟文件系统

虚拟文件系统Virtual File System ,简称 VFS )是一种位于操作系统内核中的抽象层,它为各种底层文件系统提供统一的访问入口。通过 VFS,操作系统能够把不同存储介质(本地磁盘、网络共享、光盘等)和各类文件系统的实现细节屏蔽掉,使上层的系统调用和用户程序只需要面对一套一致的接口,而无需关心文件实际存放在哪里、采用何种组织方式。

VFS 的核心目标有三点:

  1. 统一接口 :为所有文件系统提供统一的 API(如 openreadwriteclose 等),保证应用程序在对文件进行操作时的代码始终相同。
  2. 提升可扩展性 :只要新的文件系统实现了 VFS 定义的接口,就可以通过注册驱动或模块的方式无缝加入系统,而无需修改内核其它部分。
  3. 增强可移植性 :同一套系统调用在不同硬件平台或不同底层文件系统上均能工作,从而简化了跨平台软件的开发。

在 VFS 的架构中,每一种具体的文件系统(例如 ext4、NTFS、NFS、ISO 9660 等)都会实现一套内部的操作函数,并在启动时向 VFS 注册自己的驱动或模块。当应用程序发起文件操作时,流程大致如下:

  1. 系统调用入口 :用户态程序调用如 open()read() 等系统调用。
  2. VFS 调度 :VFS 接收到请求后,根据文件路径解析出对应的挂载点(mount point),进而确定使用哪一个底层文件系统。
  3. 转发到具体实现 :VFS 将请求转交给已注册的文件系统驱动,由它完成实际的磁盘读取、网络通信或光盘访问等操作。
  4. 结果返回 :底层文件系统返回操作结果,VFS 再把结果封装回系统调用的返回值,交给用户程序。

通过上述机制,应用程序能够实现 跨文件系统的透明访问 ,即无论文件位于本地硬盘、远程服务器还是光盘上,使用的代码完全相同。这种抽象不仅简化了软件开发,还为操作系统的模块化设计提供了坚实的基础。

文件系统挂载

文件系统挂载 是指把一个独立的文件系统与操作系统的目录结构(即文件树)关联起来,使得该文件系统中的文件和目录能够被正常访问和管理。简而言之,挂载的过程就是把存储介质(如硬盘分区、U 盘、光盘、网络共享等)上的文件系统“接入”到操作系统的统一命名空间中。

在大多数现代操作系统,文件系统挂载是一个必不可少的步骤,具体表现为:

  1. 识别存储设备
    系统先检测到设备的出现(如插入 U 盘、插入光驱、网络共享被建立),并确定该设备所使用的文件系统类型(ext4、NTFS、FAT32、ISO 9660、NFS、SMB 等)。
  2. 选择挂载点
    挂载点是文件树中的一个目录,系统会在该目录下“挂上”外部文件系统。挂载点本身必须是一个已存在且为空的目录(在 Linux/Unix 中常见的挂载点有 /mnt/media/boot 等),而在 Windows 中则对应于盘符(如 D:E:)。
  3. 执行挂载操作
    操作系统调用相应的挂载函数,将外部文件系统的根目录映射到挂载点。挂载完成后,用户和应用程序通过访问挂载点即可透明地读取、写入该文件系统中的文件,就好像这些文件本来就在本地目录一样。
  4. 管理与维护
  • 挂载选项 :可以在挂载时指定只读、只写、用户权限、同步/异步等选项,以满足安全性或性能需求。
  • 自动挂载 :在 Linux 中,/etc/fstab 文件或 systemdautomount 单元可以实现系统启动时自动挂载;在 Windows 中,使用 “磁盘管理” 或组策略设置网络驱动器的自动映射。
  • 卸载 :使用 umount(Linux/Unix)或 “安全移除硬件”(Windows)将文件系统从挂载点分离,以防止数据丢失。

挂载可以提供以下优势:

  • 统一命名空间 :无论底层是本地磁盘、光盘还是远程网络共享,所有资源都在同一棵目录树下呈现,简化了路径管理。
  • 跨文件系统协同 :不同类型的文件系统(如 ext4 与 NTFS)可以并存,用户无需关心底层格式,只需通过统一的路径访问即可。
  • 资源隔离与安全 :通过挂载选项可以限制对特定文件系统的读写权限,保护敏感数据不被意外修改。

相关笔记

  • 内存管理概念
  • 内存管理
  • 虚拟内存管理