F/OSS Comics 最近更新了第 13 期漫画,把时间拨回 1978 年的加州大学伯克利分校。在大众流传的极客神话里,这段历史常被简化成:Bill Joy 一个人写了 vi 和 C shell,打包成 2BSD,一年里亲手拷贝并寄出近 75 盘磁带;接着又在 1978 年底的圣诞假期顺手给刚买来的 VAX 机器写出了虚拟内存。这个故事很热血,但砍掉了最硬核的技术细节,也抹掉了一位关键的共同创造者。

把原始档案和磁带记录对一遍,你会看到另一幅画面:2BSD 根本还不是独立的操作系统,只是挂在 AT&T PDP-11 Unix 上的扩展工具包;而让 BSD Unix 真正蜕变成完整现代操作系统的虚拟内存内核,核心算法其实出自研究生 Özalp Babaoğlu 之手。

从插件包到完整操作系统:2BSD 与 3BSD 的代际跨越 2BSD(1979 年春磁带记录) 硬件底座:16 位 PDP-11 系统定位:附加软件与工具扩展包 核心组件:Pascal、ex/vi、C shell、termcap 分发规模:Bill Joy 亲手邮寄近 75 盘磁带 3BSD(1979 年 12 月发布) 硬件底座:32 位 DEC VAX-11/780 系统定位:具备核心竞争力的完整 OS 核心突破:按需分页(Demand Paging)虚拟内存 联合署名:W. N. Joy 与 Ö. Babaoglu

一套数学软件逼出的系统革命

1978 年初,伯克利的 Richard Fateman 教授遇到了一个卡脖子的工程问题。他手里有一个从 20 世纪 60 年代末在 MIT 起步的计算机代数系统 Macsyma,专门做因式分解、求导和积分这类符号计算,但旧机器的地址空间根本装不下。

按需分页机制打破物理内存瓶颈并弥补硬件缺陷(剖面示意)
按需分页机制打破物理内存瓶颈并弥补硬件缺陷(剖面示意)

Fateman 拉上另外 13 位教职员工,把美国国家科学基金会(NSF)的提案资金和系里的钱凑到一起,在 1978 年秋天买回了一台 32 位的 VAX-11/780。

机器到了,系统却是个半成品。伯克利通过合作研究协议,提前拿到了贝尔实验室 Tom London 和 John Reiser 移植的 UNIX/32V 预发布版(正式版通常标为 1979 年 6 月发布)。贝尔实验室虽然把第七版 Unix 搬上了 32 位 VAX,却偷了个懒,内存管理依然沿用老旧的整进程交换(swapping),根本没启用 VAX 硬件的虚拟内存能力。程序能用多大空间,还是被物理内存死死卡住。

更棘手的是硬件本身的缺陷。VAX-11/780 的架构里缺乏页面引用位(page-reference bits),操作系统很难直接知道哪些内存页最近被访问过,要做页面置换算法极其困难。

这时候根本不是 Bill Joy 单枪匹马冲上去写内核。Fateman 找到系统教授 Domenico Ferrari 求援,Ferrari 派出了自己的研究生 Özalp Babaoğlu。

真实的分工非常明确:Babaoğlu 负责在没有硬件页面引用位的情况下,硬生生设计出按需分页(demand-paged)虚拟内存的算法实现;Bill Joy 协助做系统集成与调试。趁着 1978 年底圣诞假期实验室人少,团队留校突击测试,在 1979 年 1 月把大部分错误修完,用这套分页系统换掉了本地原本不支持分页的 32V。两人后来在 1981 年合著了论文,专门记录怎么在缺失页面引用位的架构上把交换系统改造成分页系统。

1979 年 12 月,3BSD 正式打包发布。除了虚拟内存内核和标准 32V 工具,Peter Kessler 和 Kirk McKusick 把 2BSD 上的 Pascal 系统也移植了过来。翻开 3BSD 的原版前言,底下清清楚楚印着 W. N. Joy 和 Ö. Babaoglu 两个人的联合署名。


记忆的偏差与被遗忘的备胎

技术史一旦变成口口相传的爽文,时间线和失败者就会被顺手抹平。

原始磁带档案推翻了回忆录中关于发布时间的偏差(示意图)
原始磁带档案推翻了回忆录中关于发布时间的偏差(示意图)

我更在意的是档案里几处对不上的时间戳。Kirk McKusick 在 1985 年和 1999 年撰写的回忆文章里,都把 2BSD 的发布时间定在 1978 年年中,甚至在相关段落里漏掉了 C shell;但去查 TUHS 保存的原始磁带档案,文档上赫然写着 1979 年 5 月 10 日,内部 README 的日期则是 1979 年 4 月 19 日。甚至连最初催生了整场战役的 Macsyma,照 Fateman 后来的记述,伯克利那版名为 vaxima 的演示程序其实一直拖到 1980 年左右才真正跑起来。

历史往往由最后的打包者书写,但代码的每一行都在替沉默者作证。

另一个常被搞错的常识,是把伯克利的 3BSD 当作史上第一个支持虚拟内存的 Unix。

1982 年 3 月《AUUGN》留存的同期记录,以及 Rob Pike 在 2022 年 12 月的回忆都证实了一个平行宇宙:贝尔实验室的 John Reiser 当时也独立写出了一套分页式虚拟内存实现。伯克利的方案之所以能成为行业标准,甚至被贝尔实验室反向吸收,不是因为世上无人能做,而是他们在技术路线的正面竞争里赢了下来。

1978-1980 虚拟内存攻坚与史料真实时间线 1978 秋 购入 VAX-11/780 获 32V 预发布版 1978 圣诞假期 Babaoğlu 与 Joy 突击调试按需分页 1979 年 1 月 替换本地 32V 4-5 月发 2BSD 磁带 1979 年 12 月 3BSD 正式打包 TUHS 索引标次年 3 月 约 1980 年 vaxima 演示 真正开始运行

先秦《吕氏春秋》里讲“千腋成裘”,做底层系统从来都是这个理。大众媒体总喜欢把复杂的系统工程压缩成某一个天才在圣诞夜的灵光一闪,因为单人英雄叙事传播成本最低。

但看清这段历史真正有价值的地方,在于看懂技术演进的真实咬合机制:一个应用层教授为了跑通大型符号计算软件去凑钱买硬件,倒逼系统组研究生在残缺的硬件指令集上抠出分页算法,最后再由一个精力旺盛的工程黑客把内核、编译器、编辑器和终端库拧成一盘能直接寄给近 75 个机构的磁带。

  • 结论.应用层的极限需求才是底层系统突破的第一推手,而把实验室算法变成全行业标准的决定性一跃,靠的是工程集成与分发能力。

正是 3BSD 证明了伯克利计算机系统研究组(CSRG)不仅能写外围小工具,还能啃下最硬的操作系统内核,这才直接引来了后来 DARPA 的巨额合同。没有 1978 年底那个没有页面引用位的圣诞夜,后面 4BSD 把 TCP/IP 协议栈塞进 Unix、顺手垫高现代互联网底座的故事,根本无从谈起。