Appearance
现实世界
现实世界操作系统中的缓冲区缓存明显比 xv6 的复杂,但它服务于相同的两个目的:缓存和同步对磁盘的访问。xv6 的缓冲区缓存,像 V6 的一样,使用简单的最近最少使用 (LRU) 驱逐策略;还有许多更复杂的策略可以实现,每种策略对某些工作负载有利,而对其他工作负载则不那么有利。一个更高效的 LRU 缓存将消除链表,而是使用哈希表进行查找,使用堆进行 LRU 驱逐。现代缓冲区缓存通常与虚拟内存系统集成,以支持内存映射文件。
Xv6 的日志系统效率低下。提交不能与文件系统系统调用并发进行。系统记录整个块,即使块中只有几个字节被更改。它执行同步日志写入,一次一个块,每次写入都可能需要整个磁盘旋转时间。真正的日志系统解决了所有这些问题。
日志记录不是提供崩溃恢复的唯一方法。早期的文件系统在重启期间使用清道夫(例如,UNIX fsck
程序)来检查每个文件和目录以及块和 inode 空闲列表,查找并解决不一致性。对于大型文件系统,清道夫可能需要数小时,并且在某些情况下,不可能以使原始系统调用具有原子性的方式解决不一致性。从日志恢复要快得多,并使系统调用在崩溃面前具有原子性。
Xv6 使用与早期 UNIX 相同的基本磁盘布局的 inode 和目录;这种方案多年来一直非常持久。BSD 的 UFS/FFS 和 Linux 的 ext2/ext3 使用基本相同的数据结构。文件系统布局中效率最低的部分是目录,每次查找都需要对所有磁盘块进行线性扫描。当目录只有几个磁盘块时,这是合理的,但对于包含许多文件的目录来说,这是昂贵的。微软 Windows 的 NTFS、macOS 的 HFS 和 Solaris 的 ZFS,仅举几例,将目录实现为磁盘上块的平衡树。这很复杂,但保证了对数时间的目录查找。
Xv6 对磁盘故障很天真:如果磁盘操作失败,xv6 会 panic。这是否合理取决于硬件:如果操作系统位于使用冗余来掩盖磁盘故障的特殊硬件之上,也许操作系统很少看到故障,以至于 panic 是可以接受的。另一方面,使用普通磁盘的操作系统应该预料到故障并更优雅地处理它们,以便一个文件中块的丢失不会影响文件系统其余部分的使用。
Xv6 要求文件系统适合一个磁盘设备并且大小不变。随着大型数据库和多媒体文件对存储需求的不断提高,操作系统正在开发消除“每个文件系统一个磁盘”瓶颈的方法。基本方法是将许多磁盘组合成一个逻辑磁盘。像 RAID 这样的硬件解决方案仍然是最流行的,但目前的趋势是尽可能多地在软件中实现这种逻辑。这些软件实现通常允许丰富的功能,如通过动态添加或删除磁盘来增长或缩小逻辑设备。当然,一个可以动态增长或缩小的存储层需要一个可以做同样事情的文件系统:xv6 使用的固定大小的 inode 块数组在这样的环境中效果不佳。将磁盘管理与文件系统分开可能是最清晰的设计,但两者之间复杂的接口导致一些系统,如 Sun 的 ZFS,将它们结合起来。
Xv6 的文件系统缺少现代文件系统的许多其他功能;例如,它缺少对快照和增量备份的支持。
现代 Unix 系统允许使用与磁盘存储相同的系统调用访问多种资源:命名管道、网络连接、远程访问的网络文件系统,以及监控和控制接口,如 /proc
。而不是 xv6 在 fileread
和 filewrite
中的 if
语句,这些系统通常为每个打开的文件提供一个函数指针表,每个操作一个,并调用函数指针来调用该 inode 对该调用的实现。网络文件系统和用户级文件系统提供将这些调用转换为网络 RPC 并在返回前等待响应的函数。