实现文件系统

实现文件系统

2025 南京大学《操作系统原理》
实现文件系统

实现文件系统:敌人和朋友

敌人:读/写放大

  • 存储设备的特性:被迫只能读写连续的一块数据
  • 不能像 memory hierarchy 那样随心所欲 new/delete

朋友:局部性

  • 适当地排布数据,使得临近的数据有 “一同访问” 的倾向
  • 数据暂时停留在内存,延迟写回
2025 南京大学《操作系统原理》
实现文件系统

让时间回到 1980 年

5.25" 软盘:单面 160 KiB

  • 320 个 512B 扇区 (sectors)
  • 在这样的设备上实现文件系统,应该选用怎样的数据结构?

center

2025 南京大学《操作系统原理》
实现文件系统

需求分析

相当小的文件系统

  • 目录中一般只有几个、十几个文件
  • 以小文件为主 (几个 block 以内)

文件的实现方式

  • struct block * 的链表
    • 任何复杂的高级数据结构都显得浪费

目录的实现方式

  • 目录就是一个普通的文件 (虚拟磁盘;“目录文件”)
  • 操作系统会把文件内容解读成 struct dentry[];
2025 南京大学《操作系统原理》
实现文件系统

用链表存储数据:两种设计

1. 在每个数据块后放置指针

  • 优点:实现简单、无须单独开辟存储空间
  • 缺点:数据的大小不是 2k2^k; lseek 读放大

2. 将指针集中存放在文件系统的某个区域

  • 优点:局部性好;lseek 更快
  • 缺点:集中存放的数据损坏将导致数据丢失

哪种方式的缺陷是致命、难以解决的?

2025 南京大学《操作系统原理》
实现文件系统

文件系统设计者:先算账

160 KB 的软盘,512 字节扇区

  • 320 个扇区
  • 12-bit entry, 480B
    • 竟然只要只有一个扇区就能存下 next[]
    • 容量翻倍,也就 2 个扇区

File Allocation Table: 集中保存所有指针

  • 内存里缓存一份 FAT (天生一次也要读完一个 512B)
  • 延迟写回,读/写放大的问题就完全解决了
    • 可靠性是个大问题
2025 南京大学《操作系统原理》
实现文件系统

集中保存所有指针

集中存储的指针容易损坏?

  • nn 份就行!延迟写回,写放大就不那么严重了

center

2025 南京大学《操作系统原理》
实现文件系统

FAT: 链接存储的文件

File Allocation Table: int next[];

  • next[i] == 0: Free (本块未分配)
  • next[i] == -1: EOF (本块是文件的最后一个块)

center

2025 南京大学《操作系统原理》
实现文件系统

目录树实现:目录文件

目录就是个普通文件

  • 但在 metadata 里标记一下 (mode = directory)
    • 操作系统把数据理解成 struct dirent[]
    • Quiz: 为什么不把元数据 (大小、文件名、……) 保存在文件的头部?
  • DOS: “8 + 3” 文件名 “AUTOEXEC.BAT”
    • Linux: /etc/xdg/autostart/
    • Windows: shell:startup

center

2025 南京大学《操作系统原理》
实现文件系统

历史的包袱

总有一天,8 + 3 文件名会不够用的

  • 那就只能打补丁了 😭

2025 南京大学《操作系统原理》
实现文件系统

我们甚至可以直接观察 FAT 文件系统

观察 “快速格式化” (mkfs.fat) 是如何工作的

  • 老朋友:strace

然后,把整个磁盘镜像 mmap 进内存

  • 照抄手册,遍历目录树 (fat-tree demo),试试镜像

另一个有趣的问题:文件系统恢复

  • 快速格式化 = FAT 表丢失
    • 所有的文件内容 (包括目录文件) 都还在
    • 只是在数据结构眼里看起来都是 “free block”
  • 猜出文件系统的参数 (SecPerClus, BytsPerSec, ...),恢复 next 关系
2025 南京大学《操作系统原理》
实现文件系统

FAT: 性能与可靠性

性能

  • 小文件简直太合适了
  • 但大文件的随机访问就不行了
    • 4 GB 的文件跳到末尾 (4 KB cluster) 有 2202^{20} 次 next 操作
    • 缓存能部分解决这个问题
  • 在 FAT 时代,磁盘连续访问性能更佳
    • 使用时间久的磁盘会产生碎片 (fragmentation)
      • malloc 也会产生碎片,不过对性能影响不太大

可靠性

  • 维护若干个 FAT 的副本防止元数据损坏 (轻微写放大)
2025 南京大学《操作系统原理》