Appearance
概述
xv6 文件系统的实现分为七层,如图 1 所示。磁盘层在 virtio 硬盘上读取和写入块。缓冲区缓存层缓存磁盘块并同步对它们的访问,确保一次只有一个内核进程可以修改存储在任何特定块中的数据。日志层允许更高层将对多个块的更新包装在事务中,并确保在发生崩溃时,这些块以原子方式更新(即,要么全部更新,要么都不更新)。inode 层提供单个文件,每个文件表示为一个 inode,具有唯一的 i-number 和一些保存文件数据的块。目录层将每个目录实现为一种特殊的 inode,其内容是一系列目录条目,每个条目包含文件名和 i-number。路径名层提供像 /usr/rtm/xv6/fs.c
这样的分层路径名,并通过递归查找来解析它们。文件描述符层使用文件系统接口抽象了许多 Unix 资源(例如,管道、设备、文件等),简化了应用程序员的生活。
传统上,磁盘硬件将磁盘上的数据呈现为一系列编号的 512 字节 块(也称为 扇区):扇区 0 是前 512 字节,扇区 1 是下一个,依此类推。操作系统为其文件系统使用的块大小可能与磁盘使用的扇区大小不同,但通常块大小是扇区大小的倍数。Xv6 将其已读入内存的块的副本保存在 struct buf
类型的对象中。此结构中存储的数据有时与磁盘不同步:它可能尚未从磁盘读入(磁盘正在处理但尚未返回扇区的内容),或者它可能已被软件更新但尚未写入磁盘。
文件系统必须有一个计划,用于在磁盘上存储 inode 和内容块。为此,xv6 将磁盘划分为几个部分,如图 2 所示。文件系统不使用块 0(它包含引导扇区)。块 1 被称为超级块;它包含有关文件系统的元数据(文件系统大小(以块为单位)、数据块数、inode 数以及日志中的块数)。从 2 开始的块保存日志。日志之后是 inode,每个块有多个 inode。之后是位图块,跟踪哪些数据块正在使用。其余块是数据块;每个块要么在位图块中标记为空闲,要么保存文件或目录的内容。超级块由一个名为 mkfs
的独立程序填充,该程序构建初始文件系统。
本章的其余部分将讨论每一层,从缓冲区缓存开始。请注意那些在较低层精心选择的抽象简化了较高层设计的情况。