第 1 章 - BeOS 和 BFS 简介(Introduction to the BeOS and BFS)
1.1 BFS 的历史背景(History Leading Up to BFS)
1990 年末,Jean Louis Gassée 创立了 Be, Inc.,旨在解决当时操作系统存在的诸多问题。他认为,大多数操作系统的问题在于它们背负了多年遗留下来的包袱。这种遗留带来的代价就是性能:底层硬件的速度并没有得到充分利用。
为了解决这个问题,Be 公司从零开始开发 BeOS 操作系统和 BeBox 计算机。最初的 BeBox 使用了两颗 AT&T 的 Hobbit CPU 和三颗 DSP 芯片。设备还配备了各种插件卡,以支持电话通信、MIDI 和音频功能。这款设备的成本适中,在当时(1992 年)具有令人印象深刻的性能。在此期间,BeOS 逐渐发展为支持对称多处理(SMP)的操作系统,具备虚拟内存、抢占式多任务和轻量级线程等功能。系统的大多数功能由用户级服务器提供,内核则保持得非常小巧。BeOS 的主要界面是图形用户界面,风格类似 Macintosh。图 1-1 展示了 BeOS 的 GUI。

最初设计的 Hobbit BeBox 被设想为一种信息设备,它可以连接到网络,接听电话,并能很好地支持 MIDI 及其他多媒体设备。回顾来看,这个设计有点类似我们今天所说的“网络计算机”(Network Computer, NC)和某种形式的机顶盒的结合。
然而,这款 BeBox 的硬件设计最终遭遇了不幸的结局。1994 年 3 月,AT&T 停止了 Hobbit 处理器的生产。Be 公司因此重新设计 BeBox,转而采用更常见的元件,使用当时前景最为看好的 PowerPC 芯片。新版本的 BeBox 配备了双 PowerPC 603 处理器、PCI 总线、ISA 总线和 SCSI 控制器。它采用了市面上现成的组件,并配有一个酷炫的前面板,带有双 LED 显示器用来显示处理器的活动状态。这款设备迅速成为极客们追捧的对象。
除了修改硬件,BeOS 也做了相应调整,以支持新的硬件,并充分发挥 PowerPC 处理器的性能优势。PowerPC 版 BeBox 的出现,使得 BeOS 几乎可以作为一个常规操作系统使用。虽然最初的设计目标略有偏离,BeOS 却逐渐发展成一个功能完整的桌面操作系统。这个转型过程中确实留下了一些小瑕疵,但都在可控范围之内。
转变(The Shift)
Be 公司在 1995 年 10 月向世界宣布了 BeOS 和 BeBox,不久之后,BeBox 向开发者开放。随着曝光度的提升,系统受到了严格的审视,一些问题逐渐显现。当时,BeOS 使用一个独立于底层层次文件系统(即旧文件系统,简称 OFS)的数据库来管理有关文件的额外信息(例如电子邮件消息的头字段)。之所以采用这种分离式的数据库和文件系统设计,一部分原因是希望尽可能将代码保持在用户空间中。然而,数据库和文件系统分离之后,保持二者同步成了一个难题。此外,随着 BeOS 向通用计算领域的拓展,人们也希望它能支持其他文件系统(例如 CD-ROM 的 ISO-9660 文件系统),但原有的 I/O 架构并未为此预留空间。
1996 年春,Be 意识到将 BeOS 移植到其他 PowerPC 机器上,将大幅提升用户基数。苹果 Macintosh 的 Power Mac 系列计算机在架构上与 BeBox 相似,移植工作看来将对所有人都有利。到了 1996 年 8 月,BeOS 已能运行在多种 Power Mac 硬件上。系统运行非常流畅,并因此吸引了大量关注——因为现在可以在同一套硬件上对 BeOS 和 Mac OS 进行直接对比。在几乎所有测试中,BeOS 都完胜,这自然引发了极大的兴趣。
但在 Power Mac 上运行也暴露出了其他问题。支持 HFS(Mac OS 的文件系统)变得非常重要,而且我们发现 POSIX 支持也被广泛使用,这进一步暴露出数据库和文件系统之间同步的诸多难题。
解决方案(The Solution)
从 1996 年 9 月开始,我和 Cyril Meurillon 着手为 BeOS 设计全新的 I/O 架构和文件系统。我们清楚,原有的数据库和文件系统分离的方式已经无法为未来发展所接受。我们希望开发一个全新的高性能文件系统,它不仅要具备 BeOS 标志性的数据库功能,还要能够支持多种文件系统类型。同时,我们也借此机会清理了过去五年开发过程中积累的一些技术债务和系统垃圾。
这个项目可以明确分为两个部分。第一部分是高层的文件系统和设备接口。这部分工作包括定义文件系统和设备驱动程序的 API,管理命名空间,将程序的文件请求映射到文件描述符上,并维护所有相关状态。这部分任务由 Be 的首席内核架构师 Cyril 负责。他面临的最大挑战是要设计一个尽可能支持多线程、正确性高、不死锁且高效的文件系统 API。围绕文件系统应当具备哪些功能,以及哪些功能应由内核层来管理,我们进行了大量的反复设计。第 10 章会对这一层面的文件系统做一定的探讨,但这并不是本书的重点。
我的任务是定义磁盘上的数据结构,处理底层磁盘块的所有细节,以及执行程序发出的 I/O 请求。由于磁盘块缓存系统与文件系统紧密耦合(尤其是在日志式文件系统中),我还负责重写整个块缓存系统。
1.2 设计目标(Design Goals)
在真正着手构建文件系统之前,我们必须先明确目标以及我们希望支持的功能。有些功能是必不可少的,例如旧文件系统(OFS)所支持的数据库功能。其他功能,比如日志机制(用于增强文件系统的一致性和加快启动时间),虽然并非强制要求,但极具吸引力,因为它们在付出相对较小成本的前提下提供了诸多优势。还有一些功能,例如支持 64 位文件大小,是 BeOS 的目标用户群体所必需的。
新的 Be 文件系统(BFS)首要必须支持的功能,是旧 Be 文件系统中“数据库”的概念。OFS 支持一种包含命名字段的记录(record)概念。每个底层文件系统中的文件都对应数据库中的一个记录,当然,也可以存在仅存在于数据库中的记录。该数据库具有查询接口,可以查找满足特定字段条件的记录。OFS 还支持“实时查询”(live queries)——即持久化查询,一旦匹配记录发生变化(如新增或删除),就会自动接收到更新。这些功能全部是强制性的。
我们决定将日志机制纳入 BFS,有几个重要原因。首先,日志文件系统在启动时不需要一致性检查。正如后面会详细解释的那样,日志机制的本质决定了其始终保持一致性。这带来了若干好处:启动速度非常快,因为无需检查整个磁盘;而且避免了让不具经验的用户手动运行一致性检查程序的风险。其次,考虑到我们需要为数据库功能构建复杂的索引数据结构,日志机制能显著简化系统在故障之后的数据恢复工作。实现日志功能的开发成本也很低,这进一步坚定了我们支持它的决心。
我们支持 64 位卷大小和文件大小的决定也很直接。BeOS 的目标用户往往处理大型音频、视频和图像文件。这些文件动辄几个 GB(例如,仅 2 分钟未经压缩的 CCIR-601 视频就已超过 2^32 字节)。再加上当时磁盘容量已经普遍达到多个 GB,如果因为文件系统限制而被迫将一个 9 GB 的硬盘分成多个分区显然是不合理的。所有这些因素都表明我们迫切需要一个支持 64 位的文件系统。
除了上述设计目标,我们还有一个长期目标:让系统尽可能支持多线程并且高效。这意味着我们在设计中必须实现细粒度的锁机制,并密切关注文件系统所引入的任何额外开销。内存使用也是一个关键问题。由于BFS的主要开发平台是只有 8 MB 内存的 BeBox,我们无法奢望有大量内存可用于缓冲区。
1.3 设计约束(Design Constraints)
我们还面临一些设计上的限制。首当其冲的是工程资源匮乏。Be 的工程团队规模很小,当时只有 13 名工程师。除了我和 Cyril 以外,其他人都忙于其他项目,我们只能独自完成这项工作。而且我们并没有太多开发时间。Be 公司会定期发布软件版本,周期通常是每 4 到 6 个月一次。最初这个项目计划在 6 个月内完成。然而,由于时间紧迫、人手不足,我们几乎没有时间去探索多种设计方案,也无法对未经验证的想法进行实验。最终,BFS 的首个测试版本用了 9 个月才完成,正式版本则在次月发布。
1.4 小结(Summary)
这些背景信息为我们后续详细讲解 Be 文件系统提供了基础。理解 BeOS 是什么,以及 BFS 需要满足哪些需求,将有助于你明白:在面对多种设计方案时,我们为何选择了某一特定路径。