如果把操作系统的发展史比作《三国演义》那么本文更像《三国演义》而不是《三国志》。本系列尝试用故事化的方式讲述 Unix、Linux、BSD、GNU、Windows、macOS、Android 等操作系统背后的发展历程。文中的人物、事件和技术演进都尽量参考公开资料但为了让故事更容易理解会适当简化一些历史细节也会加入作者自己的理解。它不是一篇学术论文而是一段程序员视角的技术故事。如果读完之后你产生兴趣愿意继续查阅官方资料那这篇文章的目的就达到了。引子Unix 成功了但程序员却开始失去自由上一篇我们讲到了 Unix。Unix 从贝尔实验室走向大学。又从大学走向商业公司。它的影响越来越大。使用它的人越来越多。围绕 Unix 诞生的软件也越来越丰富。看起来一切都在向好的方向发展。但是到了 20 世纪 80 年代一个新的问题出现了。过去程序员之间经常交换代码。谁遇到问题就看看源代码。发现 Bug就顺手修一下。写出新功能也可以分享给别人。但是后来软件开始成为商品。源代码不再轻易公开。程序员开始签署保密协议。原本很自然的代码分享逐渐变成了一件“不被允许的事情”。就在这时一个非常固执的程序员站了出来。他的名字叫Richard Stallman。他想做一件听起来近乎疯狂的事既然 Unix 不再自由那就重新写一个自由的 Unix。这个项目叫GNU。第一章一个打印机引发的故事Richard Stallman 当时工作在麻省理工学院人工智能实验室。这里聚集着一群非常特别的程序员。他们喜欢研究系统。喜欢修改代码。也喜欢把自己的成果分享给别人。在那个年代他们把自己称为Hacker。这里的 Hacker并不是今天新闻里入侵电脑的黑客。而是喜欢探索技术。喜欢解决问题。喜欢把机器研究透的人。据说实验室里曾经有一台打印机。这台打印机经常卡纸。于是程序员修改了驱动程序。当打印机卡住时系统会自动提醒正在等待打印的人。后来实验室换了一台新打印机。新打印机还是会卡纸。但是这一次厂商不提供源代码。Stallman 找到一个可能拥有驱动源码的人希望对方给自己一份。对方拒绝了。因为他签署了保密协议。这件事让 Stallman 非常震动。在他看来一个程序员明明可以帮助另一个程序员。却因为一份合同不能分享代码。问题已经不只是打印机为什么不提醒卡纸。而是为什么程序员不能帮助程序员第二章过去的软件是可以互相分享的在早期计算机时代硬件非常昂贵。软件却还没有完全成为独立商品。很多程序会随着机器一起提供。程序员拿到源代码后可以自己修改。有时候一个实验室修改完程序。会把代码复制给另一个实验室。另一个实验室又会继续改进。这很像今天的开源社区。但是当时并没有 GitHub。也没有 Pull Request。甚至连“开源软件”这个词都还没有流行起来。大家只是觉得代码可以研究。可以修改。也可以分享。但随着软件行业逐渐商业化一切开始改变。软件公司发现代码本身可以卖钱。于是源代码被藏了起来。许可证开始限制用户。程序员也被要求承诺不能把代码交给别人。对很多人来说这只是商业发展的自然结果。但对 Stallman 来说这是一种倒退。第三章既然没有自由的操作系统那就自己写一个1983 年。Richard Stallman 宣布他要开发一套新的操作系统。它需要满足两个条件。第一像 Unix。第二完全自由。为什么要像 Unix因为 Unix 已经非常成熟。大量程序员熟悉 Unix。大量软件也围绕 Unix 开发。如果新系统能够兼容 Unix原来的使用习惯可以保留。很多程序也可以移植过去。但是这个系统不能直接使用 Unix 的商业源代码。它必须从头开始写。于是GNU 项目诞生了。GNU 的全称是GNUs Not Unix。翻译过来就是GNU 不是 Unix。这个名字有点奇怪。因为解释 GNU 时又会再次出现 GNU。它像一个永远说不完的绕口令。但这正是早期程序员喜欢的幽默。第四章GNU 的自由不是不要钱看到 Free Software很多人第一反应是免费软件。但 Stallman 所说的 Free重点不是价格。而是自由。一份软件可以免费。但如果用户不能查看源代码。不能修改。不能分享。那么它依然可能不是自由软件。反过来自由软件也可以收费。开发者可以卖光盘。可以提供技术支持。也可以靠软件服务赚钱。GNU 真正关心的问题是用户拿到程序之后拥有什么权利你能不能运行它能不能研究它能不能修改它能不能分享给别人所以 Stallman 经常用一句话解释这里的 Free更像自由表达中的自由。而不是免费啤酒中的免费。第五章GNU 想造的不是几个命令而是一整个系统今天很多 Linux 用户都使用过这些命令ls cp mv rm grep sed bash gcc gdb make很多人会自然地认为这些都是 Linux 命令。但严格来说其中很多工具来自 GNU。因为它们长期和 Linux 一起出现。所以大家慢慢把整套东西都叫成了 Linux。但 GNU 最初的目标远远不只是写几个命令行工具。它想创造的是一个完整的操作系统。一套操作系统需要什么需要编辑器。需要编译器。需要调试器。需要 Shell。需要 C 语言库。需要文件工具。需要构建工具。需要各种基础命令。当然还需要内核。于是 GNU 开始一件一件地写。第六章先造工具再用工具造系统GNU 的开发路线非常聪明。想写操作系统先得有写代码的工具。于是GNU Emacs出现了。程序员可以用它编辑代码。但写完代码还需要编译。于是GCC出现了。程序出错还要调试。于是GDB出现了。程序越来越多还需要自动构建。于是GNU Make出现了。系统需要命令行环境。于是Bash出现了。系统还需要大量基础命令。于是GNU Coreutils逐渐完善。GNU 就这样先打造工具。再用这些工具继续打造自己的操作系统。这像什么像一个人想建造一座城市。但他没有起重机。没有卡车。没有水泥厂。于是他先建工具厂。再用工具厂生产出来的机器继续建城市。这个过程很慢。但成果非常扎实。第七章GCC后来帮助了另一个系统GNU 项目中有一个非常重要的工具GCC。它最初是 GNU C Compiler。后来逐渐支持更多语言变成了 GNU Compiler Collection。编译器有什么用简单来说程序员写的是源代码。计算机真正运行的是机器指令。编译器负责把前者变成后者。如果 GNU 没有自己的编译器那它就必须依赖其他公司的工具。今天别人允许你使用。明天可能修改许可证。后天甚至可能停止提供。所以一个自由的操作系统最好也拥有自由的编译器。GCC 的出现让 GNU 有了自己的“兵工厂”。GNU 可以用自由软件继续生产自由软件。但是历史很有意思。GNU 原本为自己的操作系统准备了 GCC。后来GCC 却帮助 Linux 内核迅速成长。GNU 辛辛苦苦打造的兵工厂。最终先武装了另一支军队。第八章光是开放源代码还不够Stallman 很快发现一个问题。假设GNU 把代码公开出来。任何人都可以使用。但有一家公司拿走代码。修改之后。再把修改版本变成闭源软件。那么最初的代码虽然自由。后来的版本却可能再次被关起来。于是 GNU 提出了一种很特别的思路Copyleft。它显然是在模仿Copyright。Copyright 是版权。Copyleft 则可以理解为把版权反过来使用。它的规则大致是你可以使用代码。可以修改代码。也可以分享代码。但是当你把修改后的版本继续发布时也要把同样的自由留给下一个用户。这种思想后来体现在GPL。也就是GNU General Public License。GPL 并不是不要版权。恰恰相反它需要利用版权法保证代码在传播过程中继续保持自由。简单来说别人把自由给了你。你不能拿走自由之后再把门锁上。第九章GNU 什么都有了唯独缺一颗心脏经过多年开发。GNU 的工具越来越完整。编辑器有了。编译器有了。调试器有了。Shell 有了。C 语言库也有了。各种基础命令越来越丰富。GNU 距离完整操作系统似乎只剩最后一步。但这最后一步却是最关键的一步Kernel。内核负责什么管理 CPU。管理内存。管理进程。管理硬盘和设备。为上层程序提供系统调用。没有内核GNU 的工具再多也只能运行在其他操作系统上。这就像汽车已经造好了方向盘。座椅。车灯。轮胎。变速箱。甚至车载工具箱。唯独没有发动机。第十章GNU 没想造普通发动机GNU 当然知道自己需要内核。但 GNU 并不想简单地复制传统 Unix 的设计。他们想做一个更先进的内核。当时操作系统领域流行一种很有吸引力的思想微内核。传统内核通常把很多功能放在一个大内核里。进程管理。内存管理。设备驱动。文件系统。网络。全都在内核空间运行。这样的设计通常被称为单体内核。微内核则不同。它希望内核本身只保留最基础的功能。其他服务尽量放到用户空间。这样做的好处听起来非常美好。系统更加模块化。某个服务崩溃不一定拖垮整个系统。文件系统可以替换。服务可以独立升级。权限也可以更加灵活。于是 GNU 选择基于 Mach 微内核开发自己的系统。它的名字叫Hurd。第十一章Hurd 的理想很丰满Hurd 并不只是一个普通内核。它更像一群相互协作的服务。文件系统是一种服务。网络是一种服务。认证也是一种服务。传统 Unix 中很多事情必须由系统管理员完成。而 Hurd 希望普通用户也能在自己的权限范围内运行一些系统服务。例如用户可以挂载自己的文件系统。可以替换一些服务。可以拥有更多控制权。这种设计非常符合 GNU 的理念。不仅软件应该自由。操作系统里的权力也不应该全部集中在一个巨大内核手中。从设计上看Hurd 很先进。很优雅。也很有理想主义色彩。但是它太难写了。第十二章越优雅的设计有时越难落地微内核理论上很美。实际开发时却会带来很多复杂问题。原本内核内部的一次函数调用。拆分服务之后可能变成进程之间的通信。服务更多。边界更多。通信更多。调试也更加困难。而且Hurd 依赖 Mach。底层微内核的问题也会影响 Hurd。GNU 不只是想让系统能够启动。它还希望架构先进权限灵活兼容 Unix性能可靠最终还能让普通人使用。每增加一个目标开发难度就上升一层。于是Hurd 一直在开发。一直在改进。也确实能够运行。但是它迟迟没有成为成熟的主流系统。GNU 什么都有了。却一直等不到自己的内核真正长大。第十三章就在 GNU 苦等内核时一个大学生出现了时间来到1991 年。芬兰有一个大学生Linus Torvalds。他想给自己的 386 电脑写一个能够使用的类 Unix 系统。一开始这只是一个个人项目。他没有打算发动一场软件自由运动。也没有打算创造一个改变世界的商业平台。他只是觉得现有系统不够好用。那就自己写一个。这个新项目后来有了一个名字Linux。需要注意Linux 最初只是一个 Kernel。它有内核。但缺少大量系统工具。它需要编译器。需要 Shell。需要 C 语言库。需要基础命令。需要调试工具。而这些东西GNU 已经写了很多年。第十四章一个有身体一个有心脏当 Linux 出现时GNU 已经拥有了大量成熟工具。却缺少一个真正可用的内核。Linux 则相反它有了正在快速成长的内核。却缺少完整的用户空间。于是两个项目相遇了。Linux Kernel加上 GNU 工具再加上其他自由软件终于组成了一个真正能够使用的类 Unix 系统。这像什么GNU 花了很多年造好了车身。方向盘。轮胎。仪表盘。座椅。甚至连维修工具都准备好了。但发动机迟迟没有完成。就在这时Linux 推来了一台发动机。虽然最初还有点粗糙。但它真的能够转。于是这辆车终于开了起来。第十五章后来大家把整辆车都叫成了 Linux这个组合迅速发展。越来越多开发者加入。越来越多硬件得到支持。越来越多软件可以运行。发行版开始出现。服务器开始使用。互联网公司开始采用。后来超级计算机。云计算。嵌入式设备。Android 手机。都和 Linux 产生了联系。但是一个有趣的问题出现了。这套系统里内核叫 Linux。大量基础工具来自 GNU。那么整个系统应该叫什么大多数人说Linux。因为简单。好记。而且已经形成了习惯。但 Stallman 认为Linux 只是内核。完整系统中大量关键部分来自 GNU。所以应该叫GNU/Linux。这场争论持续了很多年。支持 GNU/Linux 的人认为这个名称能够提醒大家GNU 和自由软件运动作出了巨大贡献。而支持直接叫 Linux 的人则认为现代发行版不只有 GNU。还有很多其他项目。如果所有项目都写进名字系统名称可能长得像一份软件清单。第十六章Linux 还是 GNU/Linux这个问题很难有一个让所有人满意的答案。严格来说Linux 是内核。GNU 提供了大量基础工具。现代 Linux 发行版则由成百上千个项目共同组成。所以从技术上说把整个系统都等同于 Linux并不完全准确。但从现实使用来说Linux 已经成为最普遍的名称。今天人们说Linux 服务器。Linux 桌面。Linux 发行版。大家通常都知道说的是一套完整系统而不只是 Kernel。至于你喜欢叫 Linux。还是 GNU/Linux。其实都没有太大问题。但至少应该知道当你打开终端输入bash gcc gdb grep ls你使用的不只是 Linux。GNU 一直都在。第十七章GNU 失败了吗如果按照最初目标来看GNU 想创造一套完整的自由操作系统。它希望工具是自己的。用户空间是自己的。内核也是自己的。最后Hurd 没有成为主流。让 GNU 工具真正走向世界的内核是 Linux。从这个角度看GNU 似乎没有完全实现最初计划。但是如果换一个角度GNU 又取得了巨大的成功。GCC 成为重要的编译器。GDB 成为经典调试器。Bash 成为广泛使用的 Shell。GNU 工具进入无数服务器。GPL 影响了整个开源软件世界。更重要的是GNU 让人们开始认真讨论一个问题。软件到底只是商品还是一种用户应该拥有控制权的工具第十八章自由软件与开源软件不完全是一回事后来Open Source也就是开源软件逐渐成为更流行的说法。很多公司喜欢开源。因为开源意味着更多人参与开发。更多人帮助测试。代码迭代更快。生态也更容易扩大。这些都很实际。也很容易被商业世界接受。但 Stallman 始终认为开源和自由软件重点并不完全一样。开源更关心这种开发模式是不是高效。自由软件更关心用户是不是拥有应有的权利。对开源支持者来说开放代码通常能带来更好的软件。对 Stallman 来说即使自由软件有时候不够方便。自由本身也依然重要。这也是为什么GNU 经常显得非常固执。它不是只想做更好的软件。它想改变软件世界的规则。写在最后它没有等来自己的 Kernel却改变了整个时代回头看 GNU 的故事它带着强烈的理想主义色彩。Richard Stallman 看到程序员失去分享代码的自由。于是他决定重新创造一个自由的 Unix。GNU 写出了编辑器编译器调试器ShellC 语言库基础命令软件许可证一整套自由软件思想。但最关键的内核Hurd。却一直没有真正成熟。就在 GNU 苦苦等待的时候Linux 出现了。于是GNU 提供了工具和用户空间。Linux 提供了 Kernel。两个原本目标并不相同的项目意外组成了一个改变世界的系统。后来大多数人把它叫成 Linux。GNU 的名字反而逐渐隐藏在系统背后。但它从来没有真正消失。每一次使用 Bash。每一次运行 GCC。每一次输入 grep。甚至每一次讨论开源许可证。GNU 都在提醒我们软件不只是代码。它也代表着谁拥有控制权。谁可以研究它。谁可以修改它。谁又有权把它分享给别人。GNU 没有等来自己理想中的 Kernel。但它推动了自由软件的发展。也为 Linux 的崛起提前准备好了几乎整个世界。如果把现代操作系统看成一片森林。Unix 是那棵古老的大树。GNU 则像一个坚持改变森林规则的人。它没能亲手种出最大的一棵树。但后来长成参天大树的 Linux使用了它准备的工具。吸收了它推动的思想。也继承了它对自由的坚持。下一回一个芬兰大学生即将登场。他原本只是想给自己的电脑写一个小内核。但这个小项目最后却进入了服务器、云计算、超级计算机和几十亿部手机。它的名字叫Linux。