# 采访：Warner Losh，第 1 部分

* 原文链接：[Interview: Warner Losh, Part 1](https://book.bsdcn.org/freebsd-qi-kan/20200708-ji-zhun-ce-shi-tiao-you/losh)
* 作者：**BSD Now 第 362 集，2.11 BSD 复原。录制于 2020 年 8 月 5 日。**

Benedict Reuschling 和 Alan Jude 与 Warner Losh 讨论了 Unix 的历史及其有趣的细节。他们谈到了他的 2.11 BSD 恢复项目，该项目由 Unix Heritage Society（Unix 遗产协会）参与。还有他写的名为《Death Match》的东西是什么？我们希望你会喜欢这一切！我们在本期呈现第一部分，将在下期推出第二部分。

**REUSCHLING：** 欢迎 Warner。首先，对于那些还不认识你的人，你能告诉我们一点关于你自己的事情，以及你是如何与 Unix 和 BSD 结缘的吗？

**WARNER LOSH：** 当然！我自大学时代起就开始接触 Unix。我开始使用 VAX-11/750，运行 4.2 BSD，大约是在 1980 年代初期——应该是 1984 年。我一直是 BSD 用户，后来在我工作的一家公司将我们的软件移植到 FreeBSD 1.0 GAMMA 时，我也开始使用 FreeBSD，因为 Jordan Hubbard 也恰好是我们的客户。

这些年来，我在 FreeBSD 上做了很多事情。我曾是安全官，也曾在多届核心团队工作过。最近，我做了一些关于 PC 卡、CardBus、devmatch 和一些主要与优化闪存性能相关的存储工作，目的是提高我公司的视频流媒体服务器性能，你们可能都熟悉这个公司。我现在在奈飞工作，他们非常慷慨地让我优化 FreeBSD 存储系统。

**REUSCHLING：** 那么，我们可以将很多好事归功于你吗？

**LOSH：** 是的，不过如果你的机顶盒无法实时播放，请不要打电话给我。我们有很多优秀的人，他们比我更擅长排查这些问题。

**JUDE：** 你真是个 BSD 历史迷！我很期待和你聊聊你正在进行的项目，显然这个项目涉及的 BSD 比你开始时接触的那个还要早。

**LOSH：** 实际上，它是在那个版本之后发布的，尽管它的版本号较低。

**JUDE：** 对，听起来会很有趣。最近，你在 FOSDEM 上讲解了 Unix 的早期历史，后来又在 BSDCan 做了相关的演讲。你认为今天 Unix 的历史比以往更重要吗？

**LOSH：** 我认为 Unix 的历史很重要，原因有很多。Unix 在当时是一款创新的系统，它推动了很多非常有趣的创新，有些创新是人们似乎忘记了，后来又重新发现的。通过了解和理解历史，你可以理解一些早期的挑战和不同方法所遇到的问题，你还可以更好地理解我们今天所在的位置，以及我们为什么做某些事情而不做其他事情。而历史帮助我们理解为什么 Unix 会有其哲学，尽管有些东西并不完全符合这一哲学，比如说套接字的出现和它的演变，以及人们如何尝试让网络功能适配普通的文件描述符，并发现这样做会带来问题。通过了解这些事件，你可以理解为什么我们今天拥有某些事物。

另外，通过研究早期的 Unix——如果你是内核开发者，浏览早期的 Unix 代码——它更容易接触，更容易阅读，也更容易理解发生了什么。而且，在很多方面，当时使用的核心算法今天依然存在于内核中，并且主要为了适应更快的 CPU 和不同的技术而进行了现代化。这将帮助你理解发生了什么，如果你去阅读现代的 BSD 内核代码，你会有一个提前的理解。

**JUDE：** 有趣的是，我们今天拥有的许多概念都来自 Unix，并且基本上没有改变。比如管道。现在几乎每个操作系统都有管道，如果没有管道就不太有意义。如果没有 Unix，我们怎么会有这些东西，即使有些东西现在已经和 Unix 没有直接关系了？那么多核心概念都来自 Unix。

**LOSH：** 没错。管道就是这样一种东西，当时人们认为，“嗯，是的，我们来试试这个，可能有趣的是能把一堆小工具串联起来，在那些没有太多地址空间的老 PDP-11 上。”这些工具必须简单，因为空间有限，而这一概念自那时以来一直延续到许多其他操作系统中，真是相当有趣。

**REUSCHLING：** 哦，是的，特别是如果你有历史背景，知道它最初是从哪里来的，以及它是如何实现的。我每年教很多学生，遗憾的是，Unix 历史部分往往是我失去一些学生的地方，不是完全失去，但有些人会睡着。你知道如何教学生 Unix 历史而不让它变得无聊吗？

**LOSH：** 我不知道我有没有什么好方法让学生不觉得无聊。我不是老师，我没有学生在面前，所以我不知道这些方法是否有效。但我在会议上或者喝啤酒时，和人们交流时，我会讲解不同历史发展的相互关系。如果你读过 Unix 二十五年的历史，你会对发生的事情有一个很好的了解，但你不会知道像那些开发它的人，有一个朋友在贝尔实验室，悄悄地给他们提供新磁带——这样他们才能保持更新。有很多个人的细节使得这些历史非常有趣，而这些并不总是公开的。

一些小群体喜欢知道 Dennis Ritchie 曾在伯克利待过一段时间，Unix 在伯克利如此扎根，因为 Dennis 和 Ken 都在那里待过。我想我可能说错了，应该是 Ken 曾在那里休假一个学期！

知道 Unix 不仅仅是技术，Unix 也是人与人之间的关系，以及这些关系如何影响 Unix 的传播和采纳，这非常有趣。如果你能帮助人们理解不同部分是如何契合的，而不仅仅是背诵事实，那似乎效果更好。我知道我在和成年人谈话时这样做更有效。我想这对学生也会有帮助。

**JUDE：** 我认为 Kirk McKusick 的演讲中最有趣的部分之一就是个人故事。里面有很多有趣的细节，使得它变得非常吸引人。我还认为另一个方面是，要真正理解 Unix 历史，你首先得理解一些 Unix 的内容，这样你才能欣赏它开发的优雅性，以及如果有其他人参与，或者如果 A 个人没有遇到 B 个人，甚至如果他们俩没有在同一个时间和地方出现，历史本来可能会发生得非常不同。

**LOSH：** 没错。有很多人与人之间的情况，还有一些 bakeoff（比较赛）。4.1 版本变成 4.2 BSD 的原因之一是 BSD Unix 和 VMS 之间有一场 bakeoff。他们做了很多性能数据的 dump，查看不同的工作负载，以便改进 4.2 BSD。他们在这些 bakeoff 中做的很多事情都促进了 Unix 的发展，让它变得更快、更好、更稳健。最终，Unix 获胜了，因为它更快、更好，也更稳健，符合他们需要的东西。

**JUDE：** 回应 Benedict 关于教学的观点，很多时候是让人们感到它的重要性。另一个方面是看我们已经失去了多少历史，无论是某人必须基于仅有的反汇编原始二进制文件重新编写程序，还是某个磁带永远丢失了，等等。这让我们思考现在写的代码，并确保我们以某种方式保存它，以便在 30 或 40 年后，当某人想知道我们是怎么做到的，不仅能找到源代码，还能找到我们不常想到的东西——也就是围绕它的工具。

举个例子，要能够构建 FreeBSD 4，你需要一个 FreeBSD 4 系统，因为你不一定能在未来 30 年后的任何计算机上直接编译它。

**LOSH：** 这是对的。

**JUDE：** 我们可能需要思考保存的内容不仅仅是 GitHub 上的源代码历史。

**LOSH：** 是的，拥有二进制文件是很重要的，这样你就能回溯并重建事物。即使你有源代码，能够运行原始二进制文件也是非常有用的。早期的 Unix 源代码是按照 Dennis Ritchie 的风格写的，这种风格相当高级，很多现代编译器根本无法理解。如果你花费大量时间和精力，你可以找到合适的参数让它接受那段代码，但语言已经发生了细微的变化，如果这样做，并不是所有的东西都能正常工作。拥有原始的二进制文件和能够运行这些二进制文件的模拟器，对于重建历史也是非常重要的，尤其是如果你想这么做的话。

**JUDE：** 是的，说到重建历史，告诉我们你那个重建 BSD 2.11 项目的情况，我猜是补丁 0。

**LOSH：** 没错。对于那些还不知道的人，你们知道 4.2BSD，它来自伯克利的第四系列版本。他们做了 1BSD、2BSD 和 3BSD。1BSD 和 2BSD 是为 PDP-11 设计的；3BSD 和 4BSD 是为 VAX 设计的。

伯克利曾非常努力地想摆脱 PDP-11 版本，但它们非常受欢迎，以至于最终还是发布了多个版本。我们有这些版本的副本。我们有主磁带的备份，但从 2 直接跳到了 2.8，我不清楚为什么。我想可能是因为它是第 80 张磁带。还有一张 BSD2.78 磁带，上面有注释，说大约有 70 张磁带发布过。也许是这样，也许不是。但确实有 2.8、2.9、2.9.1、2.10、2.10.1，我们都有这些版本。而 2.11 版本是通过 USENIX 发布的，而不是通过伯克利。USENIX 管理了所有的磁带，实际上，早期的磁带存在一些数据损坏。事实上，损坏并不在磁带本身，而是在制作磁带的系统上，所以有些地方本应有游戏的源代码，却变成了空白块。

没有人保存早期的磁带。USENIX 说，哦，磁带有损坏，我们来重新做一版。于是，他们重新制作了磁带，最终能保存下来的最早版本是补丁级别 195，这个版本是在原始发布后大约 18 个月发布的。所以，那段时间内的所有更改都被保存了下来。

然后我们想，哦，你可以反向操作，取消应用这些补丁——因为我们都习惯了现代的补丁，做个“patch -r”，一切都会很顺利，对吧？但这些补丁是以多种格式发布到 Usenet 上的。而当它们发布时，有些是像“运行这个 shell 脚本”或“提取这个 tar 包”这样的格式。当你执行时，shell 脚本会删除文件，或者 tar 包会覆盖文件。我们没有额外的上下文可以回溯。我们不能像处理现代系统那样将“香肠厂”倒回去让它变成猪。

我偶尔会问人们，嘿，有人有原始磁带吗？人们只是说没有。因此，我就把它放在那里没有再做任何事。

后来，冠状病毒爆发了，这让我感到焦虑，甚至有失眠的夜晚。你可以一直担心这些事情，或者你可以转移注意力。所以，这个项目开始时只是为了分散注意力。我想，嗯，看看补丁吧。到底哪些信息被破坏了？事实证明，很多文件是用来替换上一版本中的内容的——所以我可以直接抓取上一版本的内容。这让我前进了一段路程，但有大约十二个文件并不完全对劲，无法编译，也无法正常工作。

然后，我能假设，他们从 4.3BSD 中获取了这些文件。对于大约一半的文件，我能够从 4.3BSD 中获取到内容，因为 4.3BSD 有更新版本，而且这些变化更大。所以，好吧，现在我有了这些。

但是，从 2.10 到 2.11，他们改变了一个东西——归档格式。以前是专为 PDP-11 设计的旧归档格式，后来他们决定切换到新的现代归档格式，因为这样做会更方便。他们可以在 VAX 上做更多的事情，并交叉编译后再转移到 PDP-11，因为与 VAX 相比，PDP-11 是非常慢的机器。

**LOSH：** 于是，他们做到了，我能够将这些代码拉进来，并将它们与 BSD2.10 和 BSD4.3 代码合并。最终，我成功地建立了一串补丁，贯穿整个过程，而且它们是连贯一致的——我的意思是，所有补丁中的信息，所有我做的重构，并没有与任何东西冲突。但那算是一个低标准——没有与任何东西冲突。你可以有一个空文件不冲突，但它依然可能完全错误，因为那个文件曾有内容。

于是，我开始思考，嗯，到目前为止，这是一个有趣的结果，但让我看看能否真的构建这个系统。我开始进行系统的引导过程，并遇到了各种各样的问题。我可以讲一个半小时，但很多问题其实挺无聊的。

最大的问题是，他们修改了汇编器，导致我开始时的系统根本无法汇编旧系统。我必须弄清楚如何使用 version-7 汇编器来汇编 BSD 二进制文件，因为版本 7 和 BSD 之间系统调用格式有所变化。我不能仅仅运行 version 7 的二进制文件；不，那样太简单了。

我必须弄清楚如何做到这一点，并使用 version 7 编译器来编译 BSD 系统调用，然后将它们链接在一起，使用 PDP-11 模拟器——我想在没有实际系统的情况下做到这一点。所以，启动的第一步是建立这个过程，然后使用我们拥有的最旧的 2.11 系统——补丁级别 195 系统——来构建一些东西。然后，我得到了生成旧二进制格式所需的最基本工具链，因为补丁级别 0 和 195 之间有一个变化，那就是补丁级别 0 有所有旧的限制。

那时有八字符的标识符，还有很多其他的限制，他们想摆脱这些限制。于是他们修改了二进制格式，以便能使用更长的符号名称。而这就带来了一个问题。我不能使用新的编译器来构建旧系统的二进制文件，因为那样就混用了不同的二进制格式类型。

待我有了基本的工具链引导，我就能够用它引导其他所有东西。昨晚，我第一次成功创建了原始系统的启动磁带，并且正在测试它。当我确认没问题后，我就可以发布它。

**LOSH：** 但在做这个过程中，我意识到，哦，这个部分缺失了，或者那个部分缺失了，或者那个能编译但不工作。在过去的六个月里，我调试了所有这些问题，从我开始熬夜以来，我已经非常接近能够宣布：“嘿，这些是磁带，你可以自己试试——这些是你需要在模拟器中使用的设置，这是源代码。”

若我有了这些，我想将每个独立的更改公开发布在 GitHub 上，以便人们可以查看历史，了解系统的历史。在补丁过程中发生了很多开发和创新，现在要访问它们真的很困难。获取每个独立的部分很难，因为它们有很多不同的格式，而且没有一种方便的方式可以浏览历史。当我使用 GitHub 的历史浏览器或 Git 命令的历史浏览器查看历史时，我可以找到事情发生的地方，这样历史就变得更加容易访问了。那就不再是被锁起来的历史了。我把它比作是一个地方，感兴趣的人可以来看看，理解发生了什么，看到进展。他们可以看到一些有趣的技巧——PDP-11 有一个非常小的地址空间。它是一台 16 位机器，地址空间只有 64 千位，通过 MMU 魔法翻倍，你有 64 千位用于代码，64 位用于数据。然后你可以做一些覆盖来交换代码，这有点像 32 位系统中动态分页的前身。

通过看这些技术，你可以看到如何让代码适应更小的空间，并且在不牺牲功能的情况下简化代码，从而使其适应可用的空间限制。

所以，这就是我开始这个项目的原因。此外，人们告诉我我做不到，这是不可能的，我不可能成功，这也是一种动力。

这是 BSD2.11 项目，如果你是我的 Twitter 关注者（我在 Twitter 上是 bsdimp），你可以看到我进展中的微小逐步，或者如果你读我的博客，你可以看到更大的进展。我不知道这段对话什么时候会播出或阅读，但在接下来的几周里，会有指向已发布的文物的链接。而当 GitHub 的内容完成时，也会发布出来。

**JUDE：** 完成后，你会将每个补丁做成一个 GIT 提交吗？

**LOSH：** 是的。每个补丁都是一个 GIT 提交，并且已发送到 Usenet 新闻组，每个补丁都有一个头部，作为提交消息，描述补丁的作用以及你需要运行的任何有趣命令。作为这个过程的一部分，我还会有一系列脚本来重新创建每个补丁。

要倒退处理，这是一项大量的手动工作，所以我自动化了它。你知道，我回到了补丁 50，并且在补丁 175 中发现了一个问题。让我感到吃惊的是，我得手动重做 150 个补丁。嗯，这很快就变得无聊了，所以我把它自动化了，我也自动化了引导过程。

现在，只需几个命令，我就可以从历史文物生成一张磁带，上面是原始的——我对原始 2.11BSD 的重建。这让我几乎能做到一切，发现哦，我缺少这个硬件类型的引导加载程序，我知道它在原始版本中有——让我去找一下。但我们还是全部重新生成，这样我就不用坐在那里输入了。我可以重新生成它，去吃点午餐，或者喝点啤酒之类的。而且我在进行过程中已经将其发布到 GitHub 上了。我将要添加的其中一项内容是一些脚本，它们将向前推进（以补充我向后推进的脚本），一直到当前的补丁级别，也就是补丁 469。你可以一直跟踪到补丁 469，这是今年早些时候发布的，可以查看内容并将补丁向前推进。

我还希望创建第二套补丁，仅仅是纯补丁。如果我创建了一系列补丁，你只需要下载补丁，运行补丁，也许再运行几个相关命令，因为尽管在 2.11BSD 中有一个构建所有内容的命令，但当二进制格式改变时，你必须先构建汇编器并安装它，然后构建 AR 程序和加载器，而且必须按特定顺序进行操作。

接着，你需要构建其他东西，一些用旧的，一些用新的，这样一切才会正常工作，且不会破坏你的系统，也不会弄成一个你无法编译修复的系统，那时你就得从磁带中提取东西来重启。

有一群人使用所谓的 PI DP-11。人们拿着历史悠久的 PDP11 前面板（你可能在 PDP-11/70 上看到）并创建了一些粘合软件，以便你能把树莓派装进去并像与旧的 PDP-11 一样与之互动。这个社区中的一些成员可能有兴趣帮助创建补丁链，一直到当前，因为——你知道——他们已经跨越了 30 个补丁。由于他们手上的磁带是补丁级别 430，而他们需要从 430 升级到 470，当你必须应用每一个补丁，而不是简单地补丁然后重建时，这就有点麻烦。这涉及到使用脚本、移除某些东西、移动某些地方或按顺序构建的概念。

有很多人已经做到了我说的这一点，回溯到最后 30、40 或 50 个补丁的起点。希望之一是，我能够将所有的补丁应用脚本，并最终得到与其他系统的快照相同的系统，或者今天存在的磁带，以验证我所拥有的重建是否合理。

因为指令中有很多地方，并不像直接运行脚本一切就会好，或者这里有五个命令你只需运行。它们并不在正常命令的底部，而是埋在文本中。我以为缺失的几个部分实际上在文本中有提到。如果我逐字阅读并记住每一行，我应该会注意到这些，但因为有大约 200 个补丁要查看，我没有这么做。这需要很多时间，而且有些补丁非常冗长。

这既是一种爱的劳动，也是一系列有趣的挑战，它考验了我对早期二进制格式的理解。我写了一篇博客，讲述了早期的二进制格式，这篇博客探讨了 PDP-11 上的格式是什么，并且也说了，现在你知道这些，这就是今天的情况。你可以把那个简化的视角映射到我们今天拥有的更复杂的视角上，我们有共享库，我们有不同的部分以不同的方式处理——这是加载到只读内存中；这是加载到可重写内存中。而这些东西可以被任何事物引入。因此，与其说有三个简单的部分，不如说一个执行程序中可能有数百个部分。研究历史的一个好理由就是帮助更好地理解当前的事物。

**JUDE：** 是的，正如你所说，因为当时的计算机受限很多，只有一个 CPU 等等，很多代码更容易理解，首先查看这些可以帮助你抓住概念，再去看现代操作系统中那些更加复杂的高级版本，因为现代操作系统有很多部件同时发生，复杂得多。

**LOSH：** 对，理解一个没有锁的算法有助于你理解这个算法在更新版中是如何锁定的。通常，当你第一次接触它时，你看到最多的就是我得锁住这个，做这个，解锁那个。锁之间是有关系的，你很容易就被这些东西分心，忽视了底层的东西。你看不到大局，因为你必须做很多事情才能让它表现得好。它往往掩盖了幕后的运作。

**JUDE：** 就像你之前提到的那样，有限的地址空间等等，有时候很多技巧可能在较小的嵌入式系统上仍然有意义，那时你只有 16MB 的内存可用。你不能像我们今天这样做，假设有几个 GB 的内存，一切都没问题。

**LOSH：** 没错。

**JUDE：** 你知道，一百 KB 在这，一百 KB 在那，开始累积起来了。

**REUSCHLING：** 是的，一切都回来了。就像看着恐龙，意识到有几块骨头缺失。我试着从现在活着的哺乳动物推测它们会是什么样子。

**LOSH：** 或者，我们有一块骨头的一部分，然后我们把这块骨头和现代鸡骨头或现代犀牛骨头进行比较，因为这两种动物看起来相似，我们就说，哦，我们能用这个来重建什么吗？这部分适合那个，所以也许它看起来像现代版本。

**REUSCHLING：** 是的，正是这样。那么，回到这个问题的博物馆部分，你在博客和演讲中提到了多次 Unix 遗产协会，那到底是什么？人们如何参与其中？

（第二部分将出现在下期！）
