乐于分享
好东西不私藏

一台废弃电脑,如何长成今天的Linux帝国

一台废弃电脑,如何长成今天的Linux帝国
这篇文章要讲一个很少被完整讲过的故事——为什么今天几乎所有服务器、大部分手机(Android 内核)、你的 Mac(macOS 内核)背后都有 Unix 的影子?这条线里有一台被嫌弃到布满蛛网的废弃电脑、一场十年的官司、一次"偷"来的图形界面、一个因为付不起钱而愤然自己写系统的教授,还有一个 20 岁大学生用几天时间改写的历史。上一篇讲了计算机硬件怎么跑起来,这一篇往上一层:操作系统到底在管什么,以及它是怎么一路打到今天这个格局的。

一、内核:一个不干具体活、只负责“分家产”的管理员

计算机的硬件能力很强,但同一时刻能不能让多个程序“同时”用?答案是需要一个协调者——内核(kernel),也就是操作系统最核心的部分。

内核自己不干“具体的活”,它干三件事:把硬件资源虚拟化后公平分给各个应用程序;挡在应用程序和硬件中间,防止程序直接摸硬件导致互相打架;通过系统调用(system call)这道门,把硬件访问能力开放出去。

拆开看,内核至少要管六件事:进程管理、内存管理、文件系统、网络功能、硬件驱动、安全机制——这六个词几乎能概括你学操作系统这门课的全部目录。

直接用系统调用编程有多繁琐?举个例子:Word 和 Excel 如果都直接调系统调用去实现“打印”,这个功能就要被开发两遍。于是有人把常用的系统调用封装成更好用的接口,这就是库(library)——分系统库(比如 libc)和第三方库两种。所以调用层级其实是两层:系统调用(底层、繁琐、效率高)和库调用(高层、省事、开发快),应用程序两条路都能走,只是取舍不同。

二、四道同心圆:为什么应用程序永远碰不到硬件

内核怎么防止应用程序“越权”?靠的是 CPU 硬件层面的保护环(Protection Ring)机制。

以 Intel 平台为例,CPU 把权限分成四个同心圆环,从内到外是 ring0 到 ring3:只有内核运行在最内层的 ring0(特权级最高),应用程序只能运行在最外层的 ring3,中间两层现实里基本用不上。ring0 映射到内存里被保护的内核空间,ring3 的应用程序完全没有权限碰它。

图1:Intel CPU 的四级保护环机制(Ring0–Ring3)

给工程师的加餐

这套机制比“内存里划一块区域”要精细得多,是两套独立机制配合工作的——CPL(Current Privilege Level)存在 CPU 的 CS 段寄存器最低 2 位里,是货真价实的硬件寄存器状态,跟内存无关,CPU 每译码一条指令都会去读它。像 HLTCLI/STI、直接写 CR3 这些非内存类特权指令,硬件在译码/执行阶段直接检查 CPL 是不是 0,不是就直接触发 #GP(通用保护异常),指令根本不会被执行;内存访问权限则由段描述符里的 DPL 字段单独检查——两套机制各管一摊,互相配合。用户态代码没有任何一条指令能把 CPL 从 3 直接改成 0。唯一的提权途径是中断门/陷阱门,或者 syscall/sysenter 这类被 CPU 严格看管的“门”——走这些门时,硬件会自动把 CS 换成 RPL=0 的选择子,CPL 才会变成 0;而且门本身在 GDT 表里也带着 DPL,会先检查你有没有资格敲这扇门。这也是为什么“内核提权漏洞”永远是安全圈的重灾区——一旦有办法绕过这套门禁逻辑,攻击者就等于从 ring3 直接摸到了 ring0。

内存本身也分区管理:BIOS 映射区(开机自检程序)、内核空间(操作系统核心)、用户空间(所有应用程序共享)。当然真实的内存分配远比“连续切几块”复杂——简单连续分配会产生碎片,实际系统要用更精细的机制来管理。

一个有意思的细节:通过图形界面/命令行启动的程序,跟启动它的那个“壳”进程是强绑定的——你注销桌面,桌面上开着的 Word 会跟着一起被关掉。而且 Windows 在 2008 年之前,Shell 是直接编译进内核里的、根本没法换掉(当年“换主题皮肤”换的只是外观,不是 Shell 本身);直到 Windows Server 2008 才第一次可以脱离图形界面、用 PowerShell 操作系统,这也是 Windows 在服务器自动化上长期落后 Unix/Linux 的一个具体原因。

三、一台被嫌弃的废弃电脑,和一场没人在意的太空游戏

现在切到主线故事:Unix 是怎么来的。

时间倒回 1960 年代末,贝尔实验室、MIT、通用电气联合搞了一个叫 Multics 的大项目,目标是做一个多用户多任务的先进操作系统。功能基本做出来了,但因为目标定义得太模糊,几家机构陆续退出,项目不了了之。

贝尔实验室的 Ken Thompson 手里正好有个业余爱好项目——一款叫 Space Travel 的太空旅行游戏,他想找台机器运行它,得先给它写个简化内核。他申请用当时的主力小型机 PDP-11,被拒绝了(PDP-11 单台售价数十万美元,贝尔实验室不批)。Thompson 只能在角落里翻出一台落后了四代、布满蛛网的废弃 PDP-7,就在这台谁都看不上的机器上,把系统写了出来。同事戏称这个“简化版 Multics”为 Unics(跟 Multics 对着起的),后来演变成了 UNIX 这个名字。

最初的 UNIX 是用汇编语言写的——性能好,但没法跨平台移植。Dennis Ritchie 提出用高级语言重写,两人在 B 语言基础上加入静态变量、指针等机制,捣鼓出了 C 语言;尽管高级语言当时效率要低大约 30%,但他们赌硬件发展会很快把这点性能差距填平。1974 年,UNIX 被完全用 C 语言重写,可移植性从此奠基——这个决定影响了此后五十年几乎所有系统软件的写法。

因为 AT&T(贝尔实验室母公司)当时受反垄断法限制,必须免费提供 UNIX,UNIX 借着论文和高校合作(伯克利是其中最重要的一个)迅速在学术圈传开。Bill Joy 在伯克利成立了专攻 UNIX 改进的研究小组,还为 DARPA 开发了 TCP/IP 协议栈(今天互联网能跑起来,这份贡献功不可没),研究成果独立发行,就是 BSD(Berkeley Software Distribution)

好景不长:AT&T 分拆后开始把 UNIX 高价商业化(System V 版本一套授权 4 万美元),跟 BSD 打了长达十年的“谁才是正统 UNIX”的官司,双方发展都因此停滞——这场内耗,某种程度上也是后来开源运动能崛起的一个历史契机。

图2:从 Multics 到 Unix / BSD 的发展脉络

四、比尔·盖茨的第一桶金:一场关于操作系统的收购

把镜头切到 PC 这条线。1980 年代初,UNIX 只能跑在用摩托罗拉 m68k 芯片的 PDP 系列上,压根没移植到用 Intel 8086/8088 芯片的 PC 兼容机——不少 UNIX 程序员当时还挺看不上 Intel 架构,觉得它“丑陋”、编程接口差。

早期 PC 上主流的操作系统是 CP/M(Gary Kildall 创立的 Digital Research 公司约 1974 年开发,面向 Intel 8080/Zilog Z80 这类 8 位处理器),是 1970 年代末到 80 年代初微机上最流行的系统——顺带纠正一个常见的以讹传讹:网上流传“CP/M 一套要两三万美元”其实经不起推敲,真实的授权费大概是几十到几百美元级别,几万美元更接近同期 PDP-11 那种小型机的价格,容易被搞混。CP/M 单用户单任务、文件系统扁平(靠 A:B: 盘符区分——这个习惯被 DOS 直接继承,Windows 至今的 C 盘/D 盘就是这么来的),跟 UNIX(多用户、多任务、层级文件系统)在设计血统上完全没有关系。

IBM 和康柏当时都想找一个便宜的操作系统方案来推动 PC 普及。这时候剧情出现了一次关键转折:Tim Paterson 在 Seattle Computer Products 写了一个刻意模仿 CP/M 系统调用接口的系统,叫 86-DOS(外号 QDOS,“Quick and Dirty Operating System”),目的是让 CP/M 的软件更容易移植过来。

比尔·盖茨通过母亲(时任 IBM 董事)的人脉接触到了 IBM 高层,花 5 万美元买断了这套 86-DOS 的代码,改造后重新命名为 DOS(Disk Operating System),用许可证模式(每套仅收几美元)而不是传统一次性买断的方式卖给 IBM。随着 PC 销量突破百万台,DOS 给微软带来了数千万美元利润——这是微软真正意义上的第一桶金,也为几年后乔布斯创立苹果、跟微软正面竞争埋下了伏笔。

但 DOS 有着无法回避的先天缺陷:单用户单任务、命令行界面、资源管理拙劣,这也是后来 Windows 95/98(内核仍然基于 DOS)频繁蓝屏的根源——这是架构层面的先天病,不推倒重来治不好。

微软怎么解决的?挖角。DEC 公司的 VAX 小型机自带一个叫 VMS 的操作系统,跟 UNIX 有相近之处,原生就支持 server 能力;后来客户更青睐流行的 UNIX(相关技术人才招聘成本更低),VAX 逐渐改装 UNIX 出售,VMS 团队被闲置了下来。比尔·盖茨把这支 VMS 核心团队整个挖了过来,在 VMS 的基础上结合 Windows 的界面重写了系统——这就是 Windows NT(NT = New Technology)。NT 内核不再是 DOS,而是 VMS,稳定性大幅提升,而且因为 VMS 原生带 server 能力,Windows 从此才有了真正能打的服务器版本;后续 Windows 2000、XP 都是在 NT 内核基础上发展来的。(那支被挖空了核心团队的 DEC,后来因为经营不善被康柏收购,康柏又被惠普收购——一整条产业链的兴衰,就藏在这一次挖角里。)

图3:Windows 系统的两条内核血统线

五、苹果、施乐,和一个被讲了几十年的“偷”字

苹果走的是完全不同的路:不做 IBM PC 兼容机,而是自研硬件(早期用 PowerPC 芯片而非 Intel x86),软硬件捆绑销售,形成封闭生态。

关于苹果的 logo——“被咬了一口的苹果”,网上流传最广的说法是致敬因同性恋身份被迫害、吞食沾了氰化物的苹果自杀的计算机科学之父图灵。这个故事讲起来确实很动人,但需要澄清一下:logo 设计者 Rob Janoff 本人多次公开否认过这个说法——真实原因朴素得多:一整个苹果轮廓在小尺寸下容易被误看成樱桃,咬一口是为了让人一眼认出“这是苹果”,同时也是“byte”(字节)的一个双关玩笑。这是一个流传极广但已被证伪的都市传说,值得顺手纠正。

图形界面的故事则是真实的:乔布斯从施乐 PARC 实验室接触到了图形界面和鼠标操作技术——施乐高层当时并不看重这项技术,担心它会冲击复印机这个核心业务,所以没有商业化。乔布斯团队后来把这套技术秘密应用到了 Apple 上。而微软这边,也在跟苹果的合作中获得了图形界面技术的授权/接触——后来苹果确实以此起诉过微软的 Windows 抄袭,但因为早期存在授权协议,官司在法律上大部分对微软有利。这场“图形界面到底是谁的”的公案,某种程度上也是个人电脑图形化时代最有戏剧性的一段前史。

六、因为付不起钱,一个荷兰教授干脆自己写了个操作系统

1990 年代,UNIX 开始全面商业化,原本免费用来做科研和教学的高校也得付费才能继续用。荷兰一位教授 Andrew Tanenbaum 就撞上了这个问题——没法继续免费用 UNIX 教学,索性自己写了一个跟 UNIX 高度相似、API 兼容的教学系统 Minix(初始版本只有 4000 行代码),带着它在欧洲各大学巡回教学(欧盟教师自由流动帮了他大忙)。

Minix 有个明显的短板:驱动程序要学生在各自的机器上手动开发,重复劳动;更麻烦的是 Andrew 教授出于“怕污染系统”的考虑,拒绝接受外部代码贡献——这种封闭作风惹恼了不少学生,其中就包括赫尔辛基大学的一名学生:Linus Torvalds

Linus 20 岁生日收到一台 80386 PC(据说来自身居芬兰信息工业部门要职的外公),原装 UNIX 因版权用不了,Minix 又太封闭——他索性自己动手,只花了几天时间就写出了一个初始版本的内核。发布到电子公告牌时,名字从“Lina”变成了 “Linux”,多半是为了跟 Unix 押个韵。这一次,Linus 反其道而行:完全开放的开发模式,任何人都能改,只要求把改动反馈回来。

图4:从 Minix 到 Linux 的诞生

这条线背后还有另一条并行的暗线:MIT 教授 Richard Stallman 发起了自由软件运动,核心主张是“程序是全人类的思想结晶,不该被商业公司独占”——口号是 “Free as in freedom”(自由,不是免费)。他发起了 GNU 项目(递归缩写 “GNU's Not Unix”,专门用来跟商业 UNIX 划清界限),做出了 Emacs 编辑器、GCC 编译器(决定了程序运行效率,这也是为什么今天国产 CPU 生态还在为一款成熟编译器发愁)等一整套周边工具——唯独缺一个内核,Stallman 的团队五年都没搞定。

1991 年,Linux 内核横空出世,天然就跟 GNU 的外围软件兼容,正好填上了 GNU 拼图里最后、也是最难的那一块。Linus 主动把 Linux 并入 GNU 阵营,遵循 GPL 协议开源——Linux 内核 + GCC 编译器 + Bash Shell,三样凑齐就是一套能跑起来的基本系统,从此吸引了全世界的黑客一起往上添砖加瓦。(严谨地说,官方名称应该是 GNU/Linux,GNU 提供了几乎全部外围软件,但因为 Linux 内核的知名度太高,Stallman 争取“正名”多年,也没能扭转大众的叫法。)

给研发/合规同学的加餐

GPL 最著名的特性是传染性——只要你的软件里用了 GPL 代码(哪怕只有 20 行),整个衍生作品理论上都要遵循 GPL、公开全部源码,二进制分发同样不能豁免。这也是为什么几乎所有 Linux 发行版都必须公开源码。但 GPL 有个例外口子:LGPL(Lesser GPL)——专门为“库”这种不能独立运行、只能被别的程序调用的软件松绑。想象一下:如果 glibc 这种几乎所有 Linux 程序(无论开不开源)都要依赖的基础库是纯 GPL,那任何调用它的闭源商业软件都会被“传染”、被迫开源,Linux 上就没法运行任何闭源软件了。LGPL 的关键让步是:允许闭源程序动态链接 LGPL 库而不必开源自己,只要求库本身的修改部分公开——这也是为什么 glibc 等系统库普遍选 LGPL 而不是 GPL:目的是让 Linux 能兼容闭源商业软件,而不是逼所有软件都开源。相对的,BSD 和 Apache 协议走的是完全宽松的路线:允许自由修改、商业化,不要求衍生作品保持开源。这也是为什么商业公司普遍更爱用 BSD/Apache 协议的代码——用得越自由,用的人就越多。GPL 和 BSD,某种意义上代表了开源世界两种不同的价值观:一种坚持“自由必须被继承下去”,一种相信“自由到不设限制才是真自由”。

图5:开源协议的宽松度光谱

七、今天你看到的 Linux 生态,是怎么长出这么多分支的

Linux 内核本身只是源代码,普通用户没法直接用——发行商的工作,就是把源代码编译成能直接安装的二进制包,再加上系统配置、logo 等自己的东西,打包发行。

发行版分两大谱系:RedHat 系(RPM 包管理):Red Hat Enterprise Linux(RHEL)、CentOS、Fedora——偏企业服务器场景,图形界面相对不是重点;Debian 系(DPKG 包管理):Debian、Ubuntu、Linux Mint——Debian 完全由社区维护、技术上通常被认为最“先进”但资料相对少;Ubuntu 是基于 Debian 面向桌面体验做二次发行,默认用 GNOME 桌面。

图6:Linux 两大发行版谱系

红帽的商业模式挺有意思,很多人一开始会理解错:自由软件不等于免费软件。红帽不靠“卖软件授权”赚钱(GPL 也不允许),而是靠卖服务——系统维护、故障响应,响应时间从 2 小时到 5 分钟不等,费用大概在 800–2000 美元/年区间,等级越高越贵。这也直接催生了 CentOS(Community ENTerprise Operating System)——把红帽发布的源码重新编译成二进制、跟红帽完全兼容,但不提供任何官方技术支持,适合不想付服务费、又有自主运维能力的团队;而 Fedora 则是红帽的“试验田”,接收社区代码、每 6 个月一个版本,功能验证稳定后才会移植进企业版。

写在最后

回头看这条线:一台被嫌弃的废弃电脑写出了 UNIX,商业化的官司和收费把 UNIX 拖入内耗,也逼出了 Minix 和 Linux;一个买断来的操作系统让微软赚到第一桶金,又靠挖角对手的团队解决了自己的稳定性问题;一场关于图形界面“谁抄了谁”的公案,塑造了今天两大桌面操作系统的雏形。操作系统的发展史,很大程度上就是一部技术理想主义和商业现实互相拉扯的历史。

这一篇跳过了 Linux 具体怎么装、Kickstart 怎么自动化批量装机这类偏实操的内容——如果有兴趣,这个话题本身可以单独写一篇(从“一张启动盘的字符画菜单是怎么做出来的”讲起,会比想象中有意思)。下一篇计划继续往上讲:进程和线程到底有什么区别、内存是怎么被“虚拟”出来的。觉得有帮助的话,欢迎转发给同样在系统这条路上的朋友。