操作系统 SJTU 版(4):文件管理

Last updated on December 16, 2025 am

这是《操作系统》SJTU-CS3601 课程的课程笔记系列。本文整理部分为“第 4 部分:文件管理”。

Lecture 15: 文件系统

  • 文件:对数据的一种抽象
    • 定义:有名字且持久化的一段数据
  • 文件系统:提供了一组操作文件的 API
  • UNIX 文件系统的 API
    • OPEN, READ, WRITE, SEEK, CLOSE
    • FSYNC
    • STAT, CHMOD, CHOWN
    • RENAME, LINK, UNLINK, SYMLINK
    • MKDIR, CHDIR, CHROOT
    • MOUNT, UNMOUNT
  • 文件系统的位置

Inode:文件的元数据

  • inode:index node,记录文件多个磁盘块的位置

    • 记录多个磁盘块号
    • 头部记录文件 size 信息
    • 每个文件对应一个 inode
    • 称为文件元数据(Metadata)
  • 文件读写操作

    • 给定 inode 和文件内偏移(offset)
    • 根据 offset 计算出对应的磁盘块号
    • 若 offset 超出 size 则返回错误
  • inode 文件系统的存储布局

    • inode 表:记录所有 inode
      • 可以看成 inode 的大数组
      • 每个 inode 使用 inode 号作为索引
      • 此时,inode 号即为文件名
    • inode 分配信息(位图)
      • 记录哪些inode已分配,哪些空闲
    • 超级块:Super Block
      • 记录磁盘块的大小、其他信息的起始磁盘块位置,等等
      • 是整个文件系统的元数据

  • inode 文件系统的基本操作

    • 加载文件系统
      • 首先读取超级块,然后找到其他信息
    • 创建新文件
      • 根据 inode 分配信息找到空闲 inode,将 inode 对应的 bit 设置为 1
      • 返回 inode 在 inode 表中的索引,作为文件名
    • 查找文件(根据 inode 号)
      • 在 inode 表中根据 inode 号定位该 inode
    • 删除文件
      • 在 inode 分配表中,将该 inode 对应的 bit 设置为 0
  • 多级 inode:单级 inode 过大的问题

    • 引入索引块:指向数据块;以及二级索引块:指向索引块;…
    • 索引块(包括二级索引块)不在 inode 表的存储区域,而是在数据区域
    • 一个多级 inode 占用的空间很少
    • 支持更大的文件:可以启用三级索引,甚至四级索引

目录:也是一种文件

  • inode 与文件名
    • inode 本身已经包含了一个文件的所有信息
      • 可以使用 inode 号(inode 表的索引)作为文件名
      • 给定一个 inode 号,就可以访问文件的所有数据
    • inode 作为文件名的缺点
      • 名字很难记住,不够 user-friendly
      • 名字依赖于 inode 表位置的名字(一旦改变了位置,就必须改变文件名)
  • 字符串的文件名
    • 以字符串作为文件名的好处
      • 在操作文件时,将文件的元数据隐藏起来,用户无需感知
      • 不依赖特定的存储设备
    • 实现字符串文件名到 inode 号的映射
      • 使用映射表,记录字符串到 inode 号的映射
      • 将该表保存在一类特殊的文件中,称为目录文件
        • 目录本身也是一个文件,同样有 inode
      • 复用 inode 机制来实现目录
  • 目录文件与目录项
    • 目录中的每条映射称为一个目录项
      • 每一条目录项记录了一个 inode 号与文件名字符串的映射
      • 一个目录可以记录很多目录项
    • 目录文件的大小(占用空间)与其记录的文件大小无关
    • 目录支持查找操作
      • 给定一个目录文件和字符串
      • 在目录文件中查找字符串,并返回对应的 inode

  • 目录的递归与根目录

    • 目录中可以记录子目录
      • 因为目录本身也是一个文件
      • 通过“/”来分割父目录和子目录
    • 最顶端的目录没有目录名(文件名)
      • 被称为“根目录”(root)
      • 根目录没有文件名,在“/”的前面什么都没有
    • 绝对路径和相对路径
      • 绝对路径:如“/home/alice/test.md”
      • 相对路径:如“./test.md”
  • 文件的查找过程

硬链接与软链接

  • 创建(硬)链接:Linux 中的 ln 命令

  • LINKLINK("Mail/inbox/new-assignment", "assignment")

    • 将严格的层次结构(树)变成有向图
      • 用户不能为目录创建 link,否则会出现环
    • 不同的文件名可以指向同一个 inode 号
  • UNLINK:删除文件

    • 删掉从文件名到 inode 号的绑定关系
    • 如果 UNLINK 最后一个绑定,则把 inode 和对应的 blocks 放到 free-list
      • 每个文件都需要一个 reference counter
  • 引用计数器(Reference count):一个 inode 可以绑定多个文件名,LINK 时 +1, UNLINK 时 -1

    • 当 reference count 为 0 时,文件被删除
    • 不允许出现环
      • 除了 ‘.’ 和 ‘…’
      • 用来表明当前目录和上一层目录而不需要知道它们实际的名字

软链接(符号链接)

  • 如何在一个磁盘上建立指向另一个磁盘的 Link

    • 无法,因为不同磁盘的 inode 命名空间是不同的(因为文件系统不同)
  • 引入软链接(符号链接): soft link (symbolic link)

    • SYMLINK
    • 增加一种新的 inode 类型
  • 创建软链接:Linux 中的 ln -s 命令

  • 硬链接和软链接的对比

  • 文件系统的一些细节
    • 文件名并不是文件的一部分
      • 文件名不是文件的数据,也不是文件的元数据(inode)
      • 文件名是目录的数据,是文件系统的元数据
      • 一个 inode 可以有多个文件名(硬链接)
    • 每个硬链接的地位都是相同的
      • 文件名就是硬链接(而不是一个文件名,一个链接名)
    • 目录所占磁盘空间通常是很小的
      • 目录仅仅负责记录文件名到 inode 号的映射
      • "文件夹"这个名字有一定的误导性

文件系统 API

  • 文件系统的系统调用 API

    • CHDIR, MKDIR, RMDIR
    • CREAT, LINK, UNLINK, RENAME
    • SYMLINK
    • MOUNT, UNMOUNT
    • OPEN, READ, WRITE, CLOSE
    • SYNC
  • 文件系统的两类元数据

    • 磁盘上文件的元数据:静态的、在磁盘中
    • 被打开文件的元数据:动态的、在内存中
  • 文件的元数据 (磁盘中)

    • 拥有者/所在组 ID:拥有该 inode 的 用户 ID 和 组 ID
    • 权限的类型
      • 拥有者、所在组、其他
      • 读、写、执行
    • 时间戳
      • 最后一次访问 (如:READ 操作)
      • 最后一次修改 (如:WRITE 操作)
      • 最后一次 inode 更新 (如:LINK 操作)
  • 被打开文件的元数据(内存中)

    • 整个系统维护了一个 file_table
      • 记录了所有打开的文件的信息
      • 包括:文件游标(file cursor)、引用数(ref_count)
      • 父子进程间可以共享文件游标
    • 每个进程维护了一个 fd_table
      • 记录了该进程每个 fd 所对应文件在 file_table 中的索引
  • 文件游标 Cursor

    • 文件游标:记录了一个文件中下一次操作的位置
      • 可以通过 SEEK 操作修改
    • 情况 1: 共享游标
      • 父进程将 fd 传递给子进程
        • UNIX 中,子进程会继承父进程所有已经打开的 fd
      • 允许父子进程共享同一个文件
    • 情况 2: 非共享游标
      • 两个不同的进程打开同一个文件

文件游标共享实例

  • write()read()

    • 可能需要分配新的 block
    • 更新 inode 的 size 和 mtime
  • close()

    • 释放 fd_table 中的相关项
    • 减小 file table 中相关项的 refcnt
    • 如果 file table 中相关项 refcnt 为 0,则将其释放
  • 删除一个打开的文件:inode 引用数变成 0,但不会被立即释放和删除

    • 直到前一个进程调用 close 将其关闭
    • 在 Windows 上,则通过"禁止删除打开的文件"实现类似效果
  • fsync

    • Block cache:缓存了最近被使用的磁盘块
      • 缓存缺失时,从磁盘中读取
      • 推迟数据向磁盘的写入
      • 寻求机会批量写入,提升性能
      • 问题:如果在写入前发生故障,可能会造成不一致
    • SYNC:保证对文件的所有修改被写入到存储设备

Lecture 16: 设备管理与驱动

参考资料

本文参考上海交通大学并行与分布式系统研究所(IPADS)操作系统课程 CS3601 华志超老师的 PPT 课件整理。


操作系统 SJTU 版(4):文件管理
https://cny123222.github.io/2025/12/09/操作系统-SJTU-版-4-:文件管理/
Author
Nuoyan Chen
Posted on
December 9, 2025
Licensed under