第四章 UNIX时代:程序员的乌托邦
上一章结尾,我们留下了一个悬念:肯·汤普森为了玩游戏,写出了UNIX。
你可能觉得这像个段子,但它是真的。1969年夏天,贝尔实验室的肯·汤普森刚当上爸爸,妻子带着孩子回娘家探亲。他一个人在家,无聊透顶,想起自己写的一个叫“星际旅行”的游戏——这游戏在Multics上跑得挺好,但Multics项目黄了,机器也被搬走了。
他现在连台能跑游戏的计算机都没有。
怎么办?自己写一个操作系统,让游戏能跑起来。
听起来像一个程序员喝多了之后的疯话。但汤普森真的干了。
他用三周时间,在贝尔实验室垃圾堆里翻出的一台没人要的PDP-7小型机上,用一种他自创的、极其精简的语言,写出了一个操作系统的内核、一个文件系统、一个命令解释器,以及——那个跑得起来的“星际旅行”游戏。
这东西后来叫UNIX。
但UNIX的故事远不止一个游戏。它是一个关于可移植性、社区协作、分裂与重生的史诗。本章我们会回答几个“为什么”:
- 为什么UNIX能打败当时所有其他操作系统?
- 为什么C语言让UNIX变得不可阻挡?
- 为什么UNIX会分裂成两个敌对的阵营(BSD和System V)?
- 为什么开源运动从UNIX的裂缝里长了出来?
先记住一个硬件前提。
硬件前提
第三代集成电路(IC) 让计算机成本大幅下降。以前只有大公司和大学才买得起一台机器,现在实验室甚至个人也能拥有了。UNIX出生的PDP-7,就是DEC(数字设备公司)生产的廉价小型机,售价才几万美元——相当于IBM大型机的1/100。
硬件的廉价化让“可移植性”成为刚需。写一个只能跑在一台机器上的操作系统没人稀罕,但写一个能跑在所有机器上的系统——那是金矿。UNIX的崛起,正好踩在这个节点上。
一、为什么UNIX比Multics更成功?——简洁与可移植
我们先回到1969年,贝尔实验室退出Multics之后。
汤普森写的第一个UNIX版本(叫Unics,和Multics开了个玩笑),用汇编语言写的。汇编语言的问题是什么?它直接对应CPU的指令集,换一种CPU,整个代码要重写。PDP-7用的是DEC的汇编,换到PDP-11(另一款热门小型机)就得完全重写。
汤普森的同事丹尼斯·里奇(Dennis Ritchie) 对他说:你重写一遍UNIX,用高级语言写,这样以后移植就方便了。
高级语言?当时的高级语言有FORTRAN、COBOL、BASIC,但没有一种适合写操作系统——它们要么太慢,要么无法直接操作硬件。里奇说:那我们就发明一种新的。
1972年,里奇和汤普森发明了C语言。C语言的设计哲学,一句话概括:“相信程序员”。它允许你直接操作内存指针,可以写出非常接近汇编码的高效程序,同时又比汇编可读性高几百倍。更重要的是,他们开发了一个C编译器——可以把C代码翻译成任意CPU的机器码。
1973年,汤普森和里奇用C重写了UNIX。从那一刻起,UNIX变得可移植了。比如有人想把UNIX移植到IBM的System/370上,只需要修改C编译器的一小部分后端代码,然后重新编译整个系统——几天就能搞定,而以前用汇编重写需要几个月。
相比之下,Multics完全用PL/I语言写的。PL/I是IBM设计的巨无霸语言,功能多到爆炸,但它的编译器在当时很不成熟,生成的代码又大又慢。而且IBM之外的机器基本不支持PL/I,Multics想移植到别的平台?几乎不可能。
这就是UNIX赢的第一个原因:用C语言写,可移植。 1970年代末,UNIX已经跑在了IBM、DEC、HP、摩托罗拉……几乎所有能买到的机器上。Multics只能跑在GE/霍尼韦尔的定制硬件上。
再补充一个当时的情景:1970年代,大学里计算机系的学生用的机器五花八门——DEC PDP-11、VAX、IBM 370、Data General Nova……每个老师都想教操作系统,但每个操作系统都不一样。UNIX来了,老师说:同学们,这个UNIX可以在我们所有的机器上跑,而且源码公开,你们回去读源码,下周交作业。
这就是UNIX横扫学术界的原因。
二、为什么UNIX的设计哲学被称为“乌托邦”?——管道与组合
UNIX的成功不光是技术层面的,它的设计哲学同样重要。
汤普森和里奇从Multics的失败中学到一个教训:别做太复杂的东西。 他们把UNIX设计得像一把瑞士军刀——小而多能,每个工具只做一件事,但做得好。
这种哲学体现在两个核心原则上:
-
每个程序只做一件事,把它做好。比如
ls只负责列出文件名,grep只负责搜索文本。你不会在ls里硬塞搜索功能。 -
通过管道(pipe)把小程序串起来完成大任务。比如你想统计一个文件里有多少行包含“UNIX”。你可以写:
cat file | grep "UNIX" | wc -l。cat输出文件内容,grep筛选出匹配行,wc -l数行数。三个小程序用管道|连接,像搭积木一样。
这就是组合式设计。你可以用无限种方式组合这些工具,实现复杂任务,而不需要写一个新程序。
这种设计把程序员从“写一切”中解放了出来。你不必去记一个巨无霸程序的一万种参数,只需要记住十几个小工具的用法,然后组合它们。
UNIX的用户为什么这么忠诚?因为一旦你学会了这种方式,再回到那种所有功能挤在一起的操作系统(比如DOS),你会觉得憋屈。UNIX给你一种“我可以掌控一切”的感觉——这就是程序员的乌托邦。
1970年代末,UNIX已经在AT&T内部的员工中流行开来,但AT&T因为反垄断同意令不能卖软件。所以AT&T做了一个决定:只要非商业用途,我们免费发放UNIX源码和二进制。
这个决定,改变了世界。
三、为什么UNIX会分裂成BSD和System V?——商业与开源的第一次碰撞
免费发放UNIX的结果是:大学和研究机构蜂拥而上。
其中最积极的是加州大学伯克利分校(UC Berkeley)。伯克利的学生和教授给UNIX加了一堆新功能:更快的文件系统(FFS)、虚拟内存改进、网络协议栈(TCP/IP)、vi编辑器等等。伯克利把自己的发行版叫做BSD(伯克利软件发行版,Berkeley Software Distribution),到1980年代初,BSD事实上成了UNIX的主流版本。
另一方面,AT&T那边也没闲着。1982年,美国司法部签署了另一份同意令,解除了AT&T进入计算机商业领域的禁令。AT&T立刻成立了一家子公司叫UNIX系统实验室(USL,UNIX System Laboratories),开始正式销售UNIX的商业版本——System V。
问题来了:BSD是基于AT&T早期的免费UNIX代码开发的,但早期代码里有些部分是AT&T的版权素材。现在AT&T要卖钱了,它说:伯克利,你们基于我们的代码开发的BSD,也得授权付费。
伯克利说:不行。我们加了那么多原创的东西,我们凭什么付钱给你?再说了,最早是你免费给的,现在翻脸收费?
这就是著名的USL vs. BSDi诉讼(1992-1994年)。这场官司打了两年,最终和解。结果是:AT&T认栽,伯克利得以发布4.4BSD-Lite(去掉了所有AT&T代码的纯BSD版本)。但现在谁还记得这些呢?损失最大的是UNIX本身:内斗消耗了几年时间,而在这几年里,微软的Windows NT异军突起,抢走了大量市场。
更重要的是,这起诉讼催生了一个新的开源项目——Linux。一个叫林纳斯·托瓦兹的芬兰学生说:反正UNIX分裂了,乱成一锅粥,我写一个自己的内核吧,谁都可以免费使用,别打官司。
我们下一章再讲Linux。
先来捋一捋UNIX分裂的后果:
- BSD继续走学术开源路线,最终演变成了FreeBSD、OpenBSD、NetBSD,以及macOS的内核Darwin(BSD的直系后代)。
- System V走了商业化道路,变成了HP-UX、AIX(IBM)、Solaris(Sun) 等,至今还在银行、航空、军工等关键系统中运行。
- 普通用户根本不知道这些。他们只知道除了Windows,还有一个“Linux”——那是另一条分支。
四、为什么自由软件运动会在UNIX的裂缝中萌芽?——理查德·斯托曼的愤怒
UNIX的分裂和商业化成了一片混乱。有人愤怒了。这个人叫理查德·斯托曼(Richard Stallman)。
斯托曼是MIT人工智能实验室的元老级程序员。1980年代初,实验室里有一台著名的PDP-10计算机,跑着一个叫ITS的操作系统(Unix之前的东西)。后来新机器到了,实验室换成了DEC的VAX,上面跑的是厂商私有的操作系统——闭源、收费、不能修改。
斯托曼想修一个打印机驱动的bug,但厂商不给源码。他气得不行。
1983年,他发起GNU计划(GNU‘s Not Unix,一个递归缩写,意为“GNU不是Unix”)。目标是:写一个完全自由的、与Unix兼容的操作系统,人人可以免费使用、修改、分发。GNU计划几乎完成了除内核之外的所有部分:编译器gcc、文本编辑器emacs、命令行工具集……
但内核——后来叫Hurd——迟迟完不成。因为它走的是微内核路线,设计得极其复杂,一直难产。
直到1991年,一个芬兰学生写的简单内核填补了这个空缺,GNU才终于有了完整的内核。那个内核就是Linux。
理查德·斯托曼创立了自由软件基金会(FSF)和GNU通用公共许可证(GPL)——一份法律文件,确保任何基于GPL代码的衍生作品,也必须以GPL授权发布。这就是“传染性开源”的源头。
GPL后来成了开源运动的宪法。它让开发者敢于贡献代码,因为他们知道,自己的代码永远不会被某家公司私有化。
而这一切的起点,正是UNIX的分裂和商业化给人带来的愤怒。如果没有AT&T突然翻脸,也许伯克利BSD会慢慢成为新的标准,自由软件运动可能就不会以如此激烈的方式诞生。历史真的是一连串的连锁反应。
五、UNIX的遗产:三条分支汇成了今天的操作系统世界
行文至此,我们不妨把UNIX的遗产理一理。它分裂成了三个大的分支,每一个都塑造了我们今天使用的操作系统:
分支一:商业化Unix(System V后代)
- HP-UX(惠普)、AIX(IBM)、Solaris(Sun)等。
- 用于银行大型机、航空订票系统、军工指挥系统。
- 你一般接触不到,但它一直在后台运行。
分支二:BSD开源分支
- FreeBSD、NetBSD、OpenBSD,以及苹果的macOS(内核Darwin基于BSD)。
- 特别提一下macOS:苹果在NeXTSTEP(乔布斯被赶出苹果后创立的公司)中使用了BSD和Mach微内核,后来1997年乔布斯回归,把这个技术带回苹果,才有了Mac OS X和今天的macOS。所以你现在用的Mac,骨子里是BSD的后裔。
分支三:Linux分支
- Linux本身不是Unix,但它兼容Unix的接口规范(POSIX),可以用同样的命令行工具、同样的编程接口。
- 安卓用的是Linux内核,互联网上90%的服务器跑Linux。Linux是Unix的后继者和发扬者。
就这么一条从1969年贝尔实验室的垃圾堆里爬起来的故事,最后统治了全世界的服务器和你手里的手机。
本章小结:UNIX时代哪些选择被固定了?
-
可移植操作系统:UNIX用C语言实现了跨平台,从此操作系统不再绑死在一款CPU上。这个选择放弃了“为特定硬件深度优化”的极致性能,换来了广泛的硬件兼容。
-
管道与组合设计:每个程序只做一件事、通过管道协作。放弃了“巨无霸单体内核”的复杂集成,换来了灵活性和可组合性。
-
代码开源传播:AT&T免费赠送非商业版本,催生了BSD和GNU。这个选择后来成了开源运动的原型,虽然AT&T后来反悔,但种子已经发芽。
-
分裂与标准战争:BSD vs System V的法律纠缠,让UNIX失去了统一,但也催生了Linux和POSIX标准。POSIX保证了不同Unix系统上的软件可以互相移植。
-
自由软件许可证(GPL):理查德·斯托曼的愤怒转化成了许可证制度。确立了“代码一经开源,必须永远开源”的互惠原则。这个选择直接影响了今天我们用的所有开源软件。
下一章预告
UNIX分裂后,一个芬兰大学生在宿舍里写了一个小内核,起初只是“想了解我的新电脑”。他发了一封邮件:“我正在写一个免费的操作系统(只是个爱好,不会像GNU那么大和专业)。” 30年后,他的系统跑在全世界80%的服务器和几十亿部手机上。
下一章:Linux的诞生——一个大学生的杰作。