跳转至

文件系统

文件的逻辑结构

image-20260827150231729

文件的物理结构(文件在外存的组织方式)

在外存怎么放

  1. 一般来说,文件的数据块 = 文件块 = 磁盘块(簇) ≠ 扇区(在大题中,有时为了方便计算,磁盘块 == 扇区)
  2. 操作系统按照磁盘块来分配外存空间。

连续分配

image-20260827151505126

链接分配

image-20260827151530658

  1. FAT常驻内存。FAT可以实现随机访问,由于FAT常驻内存,假设此时访问A文件的第二个盘块,不需要把A文件的第一个盘块调入内存,直接查FAT表然后调入相应的盘块即可,因此实现随机访问。
  2. 由于FAT可以设置下一块的序号,如果分配特殊的序号可以指明特殊的含义如最后一块、是否空闲。

索引分配

image-20260827151554973

  1. 索引分配同样能实现随机访问,原理如显式链接,只不过需要把索引块调入内存。

外存管理

在外存怎么管理,分配问题

空闲表法

image-20260827153500486

空闲链表法

image-20260827153513489

位示图法

  1. 磁盘中维护了两张独立的位示图,一张是inode 位示图,用来管理“索引节点区”;另一张是盘块位示图(数据块位示图),用来管理“数据区”。

image-20260827153536192

成组链接法

image-20260827153553897

  1. 当访问到栈底时,会把栈底对应的盘块,以上图300为例:将300中的内容拷贝到当前的空闲盘块号栈中,因此此时300就空闲了,可以被覆盖,因此300也会成为一个空闲的盘块。
  2. 成组链接法在初始的时候一定是连续的空闲块,但是随着不断地回收分配可能会出现不连续地情况。当然也有办法解决但并非考点。因此下列说法是正确的:成组链接法是将连续分配和离散分配相结合的方法,也能方便找到连续的空闲块。

显示链接的FAT表

请看2.2中的2

目录

  1. 文件系统由若干目录组成,目录也是一种文件,目录文件中的目录项,在采用索引节点的情况下,将FCB拆解为了两部分:目录项 (文件名+索引节点号)、inode节点(文件的其他数据+文件数据块指针)。

FCB

  1. 在引入inode前,FCB就是文件目录项;引入inode后,文件目录项 = 文件名 + 索引节点号。

image-20260827155443199

索引节点inode

image-20260827155457492

inode在磁盘里的时候叫磁盘inode(磁盘索引节点),放入内存后成为内存inode(内存索引节点)。

  1. 目录项里放的是索引节点编号;inode里放的是文件数据块指针。

  2. FCB里原本的数据太多,但是进行查找时我们只需要用到文件名,因此把文件名和索引指针划为一块目录项,其他数据化为索引节点,由索引指针指向索引节点,检索时只需要检索目录项即可。

  3. 创建“硬链接”的系统开销

  4. 创建了什么: 只创建了 1 个新的目录项。

  5. 发生了什么: 把这个新目录项的指针,填上源文件的 inode 编号。然后源文件 inode 里的引用计数 +1。
  6. 空间消耗: 极小,仅仅消耗了所在目录文件里的十几个字节(一个目录项的大小)。

创建“软链接”的系统开销

  • 创建了什么: 创建了 1 个新的目录项 + 1 个新的 inode + 1 个新的数据块。
  • 发生了什么: 创建一个新的目录项 + inode(FCB),该目录项中的索引节点编号置为新的inode的编号,令该inode中的文件数据块指针指向新的盘块,块中放的是目标文件的地址。
  • 空间消耗: 比较大,不仅消耗了目录项,还消耗了一个宝贵的 inode 资源和一个物理磁盘块(数据块)。

  • inode(索引节点):只存“关于文件的数据”(元数据)。包括文件大小、所有者、读写权限、创建/修改时间,以及指向真实数据存储位置的指针(物理盘块号)。

Data Block(数据块/盘块):只存“文件具体的真实数据”。比如你写的 C++ 代码、视频的字节流、或者是目录文件里的目录项。

文件共享

  1. 直接按文件名在目录文件中找也是硬链接实现的

image-20260827160656217

题型总结

文件物理结构的优缺点对比

连续分配

image-20260827162810752

链接分配

image-20260827162832928

索引分配

image-20260827162842766

常见系统调用

不要考虑FCB和inode分开,除非题目提到

image-20260827163658276

  1. 当创建文件F时,文件系统(操作系统)会先去检查inode位示图,找一个空闲的inode号,然后操作系统从inode区中找到这个inode号对应的inode,进行初始化(填入文件的创建时间、所有者、读写权限等)。然后在目录文件中新增一条F对应的目录项并把inode节点号填入新建的目录项中。此时只占用了一个inode节点空间,并没有占用任何数据区的空间,直到写入数据。
  2. 调用open()后系统遍历目录找到目标文件的磁盘 inode,将其复制到内存的活跃 inode 表中;接着在系统打开文件表中分配一个新表项,记录下读写指针(初始为 0)和打开模式,并指向内存 inode;最后,在当前进程的进程打开文件表中分配一个空闲项(假设下标为 3,即 fd=3),让它指向系统表中的那个表项,最后将数字 3 返回给用户。此过程完全没有把真实文件数据读入内存。后续调用read()等函数时,操作系统直接通过 fd 查你的进程表 -> 查系统表 -> 找到内存里的 inode -> 找到磁盘数据。
  3. 在408考试中,默认多个进程多次打开同一个文件F系统打开表中只有一个F的表项。如果一个进程多次打开同一个文件,在进程打开文件表(用户打开文件表)中会生成多个完全独立的表项,并且每次打开都会返回一个不同的文件描述符(fd)。且这些fd都会指向系统打开表中对应的唯一的表项。

打开文件表

image-20260827163715621

目录和FCB的关系

image-20260827163738366

索引节点的索引问题

image-20260827165636760

image-20260827165645537

文件操作

image-20260827170422853

补充

  1. 超级块(Super Block): 存放整个文件系统的元数据(如空闲块总数、inode总数、文件系统类型)。考点:文件系统挂载时,超级块必须读入内存。每个文件系统有一个。

  2. 虚拟文件系统 (VFS):操作系统的“抽象接口类 (Interface)”

通俗比喻:跨国公司的“万能前台” 假设你是一个只会说普通话的客户,你要去跨国公司办业务。这家公司底下有法国部门(EXT4)、德国部门(FAT32)、日本部门(NTFS)。 如果不设前台,你就要亲自去学法语、德语、日语才能和他们沟通。 为了方便你,公司设立了一个万能前台(VFS)。你只需要对前台用普通话说“把这份文件存起来”(调用标准 API write()),前台内部会自己查表,把你的话翻译成对应部门的语言并派发下去。

408严谨映射(结合C++底层实现): 在408考试中,VFS 的严谨性体现在它的多态(Polymorphism)机制上。VFS 向下兼容各种不同的底层文件系统,向上给用户提供统一的 POSIX 接口。

  • 核心结构 vnode(虚拟节点): 就像是C++里的一个抽象基类(或者包含了一堆虚函数的结构体)。它只存在于内存中。
  • 函数指针的魔法: 在 vnode 结构体里,并没有写死具体的读写代码,而是存了一排函数指针(比如 *read_fn, *write_fn)。
  • 运行过程: 当你打开一个 EXT4 格式的文件时,操作系统在内存里建一个 vnode,并把 EXT4 专用的读写函数的内存地址,填进这个 vnode 的函数指针里。当你调用 read() 时,VFS 直接执行 vnode->read_fn()。
  • 考试坑点: vnode 只在内存中有,电脑一关机就没了;而各个文件系统自带的 inode 是实实在在存在磁盘上的。VFS 扮演的就是把磁盘 inode 的信息翻译成内存 vnode 的角色。

  • 文件系统挂载 (Mount):文件目录树上的“任意门”

通俗比喻:哆啦A梦的“任意门” 操作系统的根目录树(/)就像一栋已经建好的大别墅,里面有很多房间(目录)。 所谓的挂载点(Mount Point),通常就是这栋别墅里的一个空房间(比如 /mnt/usb 这个空目录)。

  • 没挂载前: 你推开 /mnt/usb 这扇门,里面就是个空房间(或者角落里有点旧杂物)。
  • 挂载操作: 你插上一个U盘(一个新的分区,有自己的独立文件系统),操作系统施展魔法,把这个U盘绑定到了 /mnt/usb 这扇门上。
  • 挂载后: 你再次推开 /mnt/usb 这扇门,哇!你看到的不再是原来的空房间了,而是直接穿越到了U盘内部的世界。这扇门变成了一个时空裂缝(任意门)。
  • 卸载(Unmount): 魔法解除,把任意门拆掉,原来的那个空房间(以及角落里的旧杂物)又重新显露出来了。

408严谨映射: 挂载的本质,是将一个独立文件系统接入到当前操作系统的全局命名空间中。

  • 内存动作: 挂载时,操作系统的核心动作是去读取那个U盘分区的超级块(Super Block),把它读进内存,并在系统的“挂载表(Mount Table)”里登记。这样系统才知道怎么解析这个U盘。
  • 路径重定向: 当你在命令行输入 cd /mnt/usb/music 时,文件系统层层解析路径。当解析到 usb 这个目录时,系统查了下挂载表,发现:“哦!这里有个任意门!” 于是路径解析的指针直接重定向跳跃到了U盘文件系统的根节点,接着在U盘里找 music 目录。
  • 考试坑点: 挂载点目录如果在挂载前本身就存了文件,挂载后这些原文件会被隐藏,但绝不会被删除。因为路径解析在任意门那里直接跳走了,根本访问不到门背后的原空间,直到卸载后才会恢复可见。

  • 文件系统层次结构

408常考各层“自上而下”的顺序及各自负责的具体工作,重点区分逻辑文件系统与文件组织模块。

层次名称 核心功能与考点
用户调用接口 提供面向用户的系统调用(如 open, read, write)。
逻辑文件系统 处理与文件名和目录相关的操作。根据路径名找到对应的FCB(或inode),检查访问权限。
文件组织模块 负责逻辑地址到物理地址的转换,以及空闲空间的管理。
基本文件系统 向底层硬件发送读写指令,处理内存缓冲区与磁盘块之间的数据传输。
I/O控制层 包含设备驱动程序和中断处理程序,直接操作硬件。

1.用户调用接口:向系统提出请求。

通俗理解: 你来到档案馆前台,递交申请单,调用标准动作说:“我要看 test.txt 文件。”

408考点: 提供面向用户的系统调用(如 open, read, write),是操作系统与用户程序交互的统一API。

2.逻辑文件系统:按名寻址与权限核验。

通俗理解: 前台接待员去大厅目录柜,通过名字查到这卷宗的档案卡(FCB/inode)。随后看了一眼卡片,发现是“绝密”卷宗,于是要求核对你的身份证,确认你有无阅读权限。

408考点: 处理与文件名和目录相关的操作。根据路径名/文件名找到对应的 FCB(或 inode),把文件名转换为文件描述符或句柄,并检查访问权限。

3.文件组织模块:逻辑转物理与空间分配。

通俗理解: 档案馆内部机器接管,把你要求的阅读进度转换成档案盒内部的位置,并算出它物理上存放在“负二层、B区、第3个架子”。如果你要存新卷宗,它还要负责用本子(位示图)帮你挑一个空架子。

408考点: 负责逻辑地址到物理地址的转换(利用FAT或多级索引表),以及空闲空间的管理。

4.基本文件系统:下发读写指令与缓冲传输。

通俗理解: 档案馆中枢系统向底层的机器臂发送具体的“提取3号架”指令,并准备好大厅的临时阅览桌(内存缓冲区),负责把抽出来的档案平稳放置在桌面上交接。

408考点: 向底层硬件下发具体的读写指令,处理内存缓冲区与物理磁盘块之间的数据传输。

5.I/O控制层:真正驱动硬件执行。

通俗理解: 底层的机器臂(硬件)真正通电启动,精准移动抽出档案盒。如果在移动中遇到轨道卡壳,会发出警报(中断处理)。

408考点: 包含设备驱动程序和中断处理程序,直接操纵底层硬件完成动作。

  1. 当你拿到硬盘的第0号主引导扇区(物理空间 512B),你提取出了里面的主引导记录 MBR(逻辑数据 512B),这份记录由三部分拼接而成:
  2. 主引导程序(446字节) 👉 负责干活的代码。
  3. 磁盘分区表 DPT(64字节) 👉 硬盘的分区划分图(C盘、D盘在哪)。
  4. 结束标志(2字节) 👉 固定的 55AA,证明这是个合法的引导记录。