MINIX 30年经验教训

时间:2024-04-01 14:56:20

作者: Andrew S. Tanenbaum,阿姆斯特丹*大学科学学院计算机科学系名誉教授。
译者:孙薇
责编:钱曙光
本文为《程序员》文章,未经允许不得转载,更多精彩文章请订阅2016年《程序员》

Linux已经为众人所熟知,而它的直接始源——MINIX到现在也有30年历史了,如此高龄的软件却还依旧充满生机。MINIX的故事,以及它和Linux的出现历史流传并不广泛,也许从MINIX的开发上我们能学到一些经验教训。其中有些是关于操作系统的,有些是关于软件工程的,还有一些是关于其他领域的(比如项目管理)。无论MINIX还是Linux都不是凭空而来。两者的出现都有很多的相关历史,因此为了正确理解本文,我们先要对它做个简单的介绍。

要点

  1. 每个设备驱动都应当按照独立的用户模式进程来运行。
  2. 软件可以维护很长时间,在设计时应当有前瞻性。
  3. 想让人们接受全新、颠覆性的概念十分困难。

1960年,在麻省理工学院有一个跟房间差不多大小的真空管科学计算机,名叫IBM709。尽管远远比不上如今的电脑——苹果iPad比它快7万倍,RAM也比它大7300倍——但IBM709已经是那时世界上最强大的电脑了。使用者一般在80列穿孔卡片上用FORTRAN来编写程序,并将这些卡片拿给操作员执行人工读取。几个小时之后,打印在132列折叠式记录纸上的结果出炉。在FORTRAN语句中就算漏掉一个逗号,都会导致编译错误,而致使程序员几个小时的时间付诸流水。

为了给用户提供更好的服务,麻省理工开发了一套新系统,叫做兼容分时系统(CTSS)。用户可以使用交互式终端来操作,等待时间也从数小时减到数秒,同时后台还能运行旧式的批处理任务。在1964年,麻省理工、贝尔实验室联合那时还是电脑供应商的通用电气公司,一起参与开发了它的后续系统,这个新系统能够同时为波士顿地区的数百名用户提供服务。我们可以把它当作云计算0.0版本,这个系统被称为MULTICS(MULTiplexed Information and Computing Service)。长话短说,MULTICS在初期问题很多,第一个版本所需求的RAM就超出了GE 645的288KB内存。最后在改进了PL/1编译器之后,MULTICS终于得以启动运行。然而,贝尔实验室很快就失去兴趣并退出了这个项目,留了一个开发人员Ken Thompson。Thompson有着勃勃雄心,他希望能在廉价的硬件上复制一个缩减版的MULTICS。在1973年MULTICS投入商用后,它在全世界揽收了大量的安装份额,最后停止使用的记录是在2000年10月30日,之间整整运行了27年。

回到贝尔实验室之后,Thompson找到了一台迷你电脑PDP-7,他在这台电脑上用汇编语言编写了MULTICS的删减版。由于每次只能服务一名用户,Thompson的同事Brian Kernighan将其称为UNICS(UNIplexed Information and Computing Service)。尽管这个称呼带有讽刺意味的双关含义,象征着MULTICS被阉割成了UNICS,却还是沿用了下来,不过之后逐渐被拼为UNIX。由于已经不能算是缩略词了,有时候也写作Unix。

1972年,Thompson与贝尔实验室的另一名同事Dennis Ritchie组成了搭档,并为Unix作了一个编译器,而Ritchie正是C语言的设计者。他们一同在PDP-11迷你电脑上用C语言实现了UNIX。后来,UNIX又出了几个内部版本,直到1975年贝尔实验室以300美元的价格将UNIX V6权授给大学使用。由于PDP-11大受欢迎,UNIX也很快在全世界流行起来。

在1977年,悉尼新南威尔士大学的John Lions在V6的源代码中撰写了注释,逐行解释其含义。全世界有数百所大学开始使用Lions的书作为UNIX V6教程。

当贝尔实验室的拥有者听说有数千名学生在学习他们的产品时,全都大吃一惊——This had to stop. 在下一个版本中(1979年的V7),官方明确禁止任何人用Unix写书或者给学生授课,导致操作系统课程回归到单纯的理论授课或模拟器模式,全世界的教授为之沮丧不已。UNIX的早期历史在Peter Salus 1994年的书中都有记录。

MINIX的创建

直到1984年我决定利用业余时间改写UNIX V7,彼时我在阿姆斯特丹*大学授课,希望这次改写能给学生们提供一个UNIX兼容的操作系统。我为这个名叫MIni-uNIX或者MINIX的系统设定的目标是IBM的新款PC,因为这款机器足够廉价(1565美元起),学生们买得起。由于早期的PC不带硬盘,在我的设计中兼容V7的MINIX要求配置是:256KB RAM的IBM PC,加一个360KB 5寸软盘。这个配置要远远低于PDP-11 V7的要求。尽管建议配置很低,但我从一开始就知道,为了编译构建整个系统,我需要更好的配置:尽可能达到最大的RAM(640KB)以及2个360KB的5寸软盘。

MINIX的设计目标如下:

  1. 构建运行在IBM PC上的V7克隆,载体是一个360KB的软盘;
  2. 将系统设计为“自托管”,即自动执行构建和维护;
  3. 所有源码完全公开,人人都能拿到;
  4. 保持干净的设计,方便学生理解;
  5. 让(微)内核尽可能保持较小,因为内核故障是致命的;
  6. 将操作系统的其他部分分成独立的用户模式进程;
  7. 保持Hide interrupt处于很低的水平;
  8. 只用传递明确协议的同步消息来通讯;
  9. 尝试让系统端口容易移植到未来的硬件中。

最初开发的时候,我用自己的家用IBM PC运行着与Mark Williams一致的V7克隆版,这份系统由加拿大滑铁卢大学的一名毕业生编写,但源码是不公开的。最初使用一致的版本很有必要,因为我没有C编译器。当程序员Ceriel Jacobs根据我自行研制的阿姆斯特丹编译器套件移植了一个C编译器后,系统就可以自托管了。因为使用MINIX编译,我对任何Bug和缺陷都非常敏感。建议所有开发者都尽可能早地亲自尝试自己开发的系统,这样就能发觉用户遇到的问题。

经验:自己试用自己的产品。

微内核确实很小,里面只有调度器、低级别的程序管理、进程间通讯与设备驱动。尽管设备驱动也编译到了微内核的执行程序中,但实际上它们是独立运行的。微内核也被编译为独立运行的可执行程序。而运行系统的每个其他组件,包括文件系统与内存管理器在内都是作为单独的程序,在单独的进程中运行。由于我使用的机器(IBM PC:CPU 8088)缺少内存管理单元(MMU),虽说可以采取捷径将所有内容打包到一个可执行文件中,但为了让这个设计在有MMU的CPU上也能运行,我决定不用这个方案。

大约花了两年时间,只用晚上和周末,我终于让这个系统运行起来了。但是运行一个小时就会毫无缘由的崩溃,也没有可辨识的模式。裸机Debug调整操作系统,问题仍旧防不胜防,我几乎想要放弃这个项目了。

然后我做了最后一次努力。我写了一个8088模拟器,在上面运行MINIX,这样崩溃时我就能获得正确的dump文件和堆栈追踪。结果吓了一跳,使用模拟器运行MINIX毫无问题,数日甚至数周还在正常运作,一次也没有崩溃。然后我完全的迷惑了。我对一名学生Robbert van Renesse提到了这个奇怪的情况,他告诉我传说8088会在过热时产生中断。虽然在8088的文档中没有这样的记录,他还是坚持有这样的说法。因此我插入了代码来捕捉中断。一个小时之内,我在屏幕上看到了这条信息:“你好,我出现中断了,这条信息不会再次出现。”我立即制作需要的补丁来捕捉中断。之后MINIX就能正常运行并准备发布了。

经验:别盲目相信文档,有可能是错的。

Van Renesse随口一句对三十年后的今天影响巨大,如果他没提过中断的事情,也许我已经在绝望中放弃了。如果没有MINIX,很难想象Linux的出现——Linus Torvalds在详尽学习了MINIX的源代码之后,用它为基础写出了Linux。没有Linux,也就没有基于其上构建的Android系统。没有Android,苹果和三星的股价可能会与今天有很大的不同。

经验:听取学生的意见,他们可能比你知道的更多。

大部分的基础工具都是我自己写的,MINIX 1.1包括有60的工具,从ar到wc,通常大小约在4kB左右,现在的引导装载程序要比它们大100倍。MINIX的所有内容,包括二进制文件和源代码刚好能放在8张360KB的软盘中。其中四张是启动盘、根文件系统、 /usr和/user (见图1)。另外四张包含全部的操作系统源代码,还有60个工具源代码。只有编译器的源码没有放进去,因为实在太大了。

经验:微软的前CTO Nathan Myhrvold的观点是正确的:软件就是煤气;会扩张至充满整个容器。

MINIX 30年经验教训

图1 这是四张原始5英寸的MINIX软盘

开发人员想要打破这种“规则”也是有可能的,但必须付出很大的努力。默认规则就是“更加膨胀”。

找到分发源码的办法是个大问题。1987年几乎没人联网,我决定写一本讲这个源码的书,就像Lions之前做的那样。这本书由Prentice Hall出版发行,所有源代码都作为书籍的赠品。在讨论之后,Prentice Hall同意以打包的形式来出售这本书,包括8张5英寸软盘,以及500页的手册,售价为69美元,基本上与制作成本相当。

Prentice Hall并不理解什么是软件,他将软件按成本出售的行为当作增加书籍销量的手段。后来在高可用的1.44MB3英寸盘出现时,我又做了一个新的3英寸版。

经验:无论你的产品多有需求,首先需要有推广或分发的方式。

在发布数日后,USENET新闻组comp.os.minix就开启了。不到一个月就获得了4万名读者,考虑到能访问USENET的人并不太多,这个数字非常可观。MINIX立即受到了推崇。

很快我就从现代计算机文化书店的联合创始人Dan Doernberg那里收到了一封邮件,邀请我去硅谷做个MINIX相关的演讲。刚好我要去旧金山湾区参加一个会议,就接受了邀请。我以为他在店内放套桌椅让我签售呢,没想到他租了圣塔克拉拉会议中心,还做了广泛的宣传,整个会议中心满都是人,演讲过后的答问环节持续到午夜。

之后我收到数百封邮件,要求添加这个或那个功能。由于担心系统过大,需要更昂贵的硬件才能运行,超出学生们的预算,有一些请求被我拒绝了。很多人包括我在内,都希望GNU/Hurd或者BSD承担开源系统的重任,以便我能继续专注于教学。

人们也提供了很多建议,其中有些非常有用。在这许多贡献者中,有一个名叫Jan-Mark Wams的人,他编写了一个非常有用的测试套件,帮助系统Debug。他还编写了一个新的压缩程序,比那时的很多现有程序要优秀,然后系统的发布内容减到了两张盘。即便后来有了在线发布版,软盘版也非常重要,因为有56kbps猫的人很少。

经验:大小有别。

1985年,Intel发布了386处理器,配合全保护模式的32位架构。在很多用户的帮助下(特别是澳洲的Bruce Evans),我发布了MINIX的32位受保护模式版本。尽管当初8088只有一个模式,但由于我对未来的硬件早有预见,从第一天起新版本的代码就被清楚的分为能在“核心模式”中运行的,以及能在“用户模式”中作为独立进程运行的。等到386出现时,我们因此受益良多。另外,在原始代码中我明确地将物理地址与虚拟地址区分开来,虽然在8088中没有什么作用,但在386上起了很大作用,使得移植更为简单。此时在阿姆斯特丹*大学还有两个人:Kees Bot和Philip Homburg制作了32位有虚拟内存的版本,不过我决定坚持使用Evan贡献的那个版本,因为它更接近原始设计。

经验:尝试在设计时符合未来硬件的需求。

到1991年,MINIX 1.5被移植到了Apple Macintosh、Amiga、Atari和Sun SPARCstation上,以及其他一些平台。

MINIX 30年经验教训

图2 四个不同平台的MINIX 1.5

经验:如果不依赖硬件的特殊性能,移植到新平台时会更简单。

随着系统的发展,总有意想不到的地方出现问题。其中跟网卡驱动相关的特别讨厌,因为无法调试。最后有人发现,网卡与所标注的规格不符。

经验:跟软件一样,硬件也会有Bug。

硬件“特性”有时可以被视为硬件的Bug。在意大利主流电脑供应商Olivetti将MINIX移植到PC上时,由于无法解释的原因出现了问题,最后发现是因为Olivetti键盘上的几个键与IBM键盘所返回的扫描代码不同。这让我想到,很多国家有自己的标准化键盘,因此我对MINIX做了修改,让它对多个键盘提供支持,并在安装系统时可作出选择。对于意大利、法国、德国等国家的人来说,这种修改非常有用。

经验:当生命给你又酸又苦的柠檬时,你可以把它做成又甜又好喝的柠檬汁。遇到不如意,你可以让它变成好事。

Linus Torvalds买了一台PC

1991年1月5日,默默无闻的芬兰赫尔辛基大学学生Linus Torvalds做了一个重要的决定。他买了一个速度飞快(33MHz)、容量很大(4MB RAM,40MB硬盘)的PC,主要是为了运行和学习MINIX。在1991年3月29日,Torvalds在USENET新闻组(comp.os.minix)发布了第一条消息:

“大家好,我已经运行minix一周了,现在升级到386-minix(很好用),准备下载gcc……”

他的第二个帖子是在1991年4月1日发布的,回了别人一个简单的问题:

“RTFSC(阅读源代码),里面满是注释和解决方案,应该非常清楚……”

这个帖子证明了在10天内,Torvalds就彻底地学习了MINIX的源代码,并对没学过源代码的人表示了鄙视。MINIX那时的目标就是要让学生很容易的学习。在Torvalds的个例中,结果显然很成功。

然后到了1991年8月25日,Torvalds又发了一个帖子:

“致使用minix的人,你们好,我正在为386(486)AT制作一个免费的操作系统(只是个人兴趣,不会像GNU那样大,也没那么专业)。这个系统是从4月开始准备的,现在已经准备完毕。我希望喜欢/不喜欢MINIX的人都能给我些反馈,因为我的操作系统有些类似,除了其他的,在文件系统中也有着同样的物理布局。”

第二年,Torvalds在继续学习MINIX,并使用它开发了自己的新系统。这就是第一代Linux的内核。在Linux的核心中,仍能看到MINIX的文件系统和源树布局的残余痕迹。

在1992年1月29日,我向comp.os.minix发布了一条消息,表示微内核除了性能之外都比单体设计更优秀。这个帖子引发了网路论战,即便到了24年后的今天,全世界也有很多学生给我发消息说明自己的站队方向。

经验:传说大象记忆力超群,而互联网就像一头大象,拥有过目不忘的本领。

当心你放在互联网上的东西,有可能在数十年后仍会出现在你面前。

对一些人来说,性能更重要。Windows NT就设计成了微内核的模式,但后来由于性能不够,微软转向了混合型设计。在Windows NT、2000、XP、7、8和10之中,底层都有一个硬件抽象层来隐藏主板的差异,在那之上是处理中断的微内核、线程调度、低级进程间通讯以及线程同步,再之上是Windows Executive,包括一群负责流程管理、内存管理、I/O管理、安全性等功能的独立组件,共同组成了操作系统的核心。就像MINIX那样,它们通过定义明确的协议来通讯,不过在MINIX中使用的是用户进程。NT及后继系统都属于混合型系统,所有这些组件都在内核模式中运行,环境切换较少,性能更好。因此,从软件工程师的角度来看,这属于微内核设计,但从可靠性的角度来看还是单体架构,任何组件中的某个Bug都会导致整个系统崩溃。苹果的OS X也是类似的混合型设计,底层是Mach 3.0的微内核,其上层(Darwin系统)脱胎于FreeBSD。

同样值得一提的是嵌入式计算的情况。在嵌入式计算世界中,可靠性要比性能更重要,因此微内核成为主流。QNX是一个类UNIX的商用实时操作系统,广泛用于汽车、工厂自动化、发电厂与医疗器械行业。L4 microkernel11运行在无线射频芯片上和安全处理器之上,前者已有全世界10亿多台手机在使用,后者也有iPhone 6等的新型iOS设备在用。L4很小,其中一个版本只有大约9000行C代码,对于单体系统来说简直不可思议。不过由于历史问题,在微内核上仍有争议,而且性能也有些低。

关于MINIX的新研究是尝试在微内核之上建立容错的、多服务器的、兼容POSIX的操作系统。

1992年在新闻组comp.os.minix里我也指出了这一点:将Linux与386架构紧密结合不是个好主意,因为RISC机器很快就会成为市场主流。在很大程度上,这也是正在发生的事情,有超过500亿(RISC)ARM芯片上市。大多数智能手机和平板电脑都使用了ARM CPU,包括高通骁龙、苹果A8和三星Exynos所使用的变种。此外,64位的ARM服务器和笔记本也开始出现。最终Linux被移植到ARM上,不过要是一开始没有跟x86架构绑得太紧,移植应该更容易一些。

经验:不要以为如今的硬件永远能占据主流市场。

也是在这个关键的时候,Linux与GCC编译器绑定在一起。

经验:标准出现时(比如ANSI),请紧跟标准。

除了Linux的真正出现,在1992年还有一个很大的发展。AT&T起诉BSDI公司与加州大学,声称BSD包含了AT&T的代码片段,此外BSDI的电话编号1-800-ITS-UNIX违反了AT&T的知识产权。这个案子到了1994年达成庭外和解,BSD被判有罪,中间给了新的Linux系统很大的发展空间。如果AT&T作出更明智的选择,购买BSDI作为市场营销部门,则有着这样强大而成熟的对手,Linux可能永远不会有机会崛起。

经验:如果你是世界上大公司的老板,有小的创业公司出现在你关心却一无所知的领域,就把它买下来。

在1997年,已经兼容POSIX的MINIX2发布了,我撰写的《操作系统设计与实践》一书也更新到第二版,合著者是Albert Woodhull。

到了2000年,我最终说服了Prentice Hall发布MINIX 2,并在网上免费发布所有源代码。这件事本该早些做,特别是原始协议允许大学进行无限的复制,而且卖给出版商的时候也是成本价格。

经验:在采取策略后,应当时不时回头检视一下。

作为研究项目的MINIX

MINIX 2又缓慢发展了几年,但到了2004年方向出现了巨大转变,那时我从荷兰科学研究组织收到了一笔拨款,可以将纯粹的爱好变为严肃的、有资金资助的研究项目。在2004年之前,我都没有外部资金来源。后来我又陆续收到几笔赠款,总共300万美元,作为研究如何将MINIX打造为可靠操作系统的经费。

经验:对重要的东西做研究可以让你获得研究经费,即便它游离于主流之外。

当然,MINIX并非唯一关注微内核的研究项目。我们后来又做了些研究,包括运行时替换崩溃的组件,这是自修复系统的第一步。事实上,现在MINIX已经可以做些事情了:无需重启,替换一些崩溃的核心操作系统组件,不会影响应用进程。没有其他团队能做到这一点,这为我们的团队树立了信心。

经验:早期成功能够鼓舞士气。

这种变化能实现最小权限原则,在像Windows或Linux这样的单体系统中,如果出现故障则驱动有权删除磁盘内容;在MINIX中,微内核的设计不允许这种做法。

经验:每个设备驱动都应当以非特权模式,按照独立用户模式方式来运行。

微软显然很了解这一点,为Windows XP以及后续系统引入了用户模式驱动框架。并鼓励设备驱动按照用户模式的方式来编写,就像MINIX那样。

2005年,我被邀请参加ACM的操作系统准则研讨会,这是操作系统研究的最高荣誉了。我打算在演讲上正式宣布MINIX 3发布,中途我脱掉了上衣,露出有MINIX 3字样的T恤。从这天起,MINIX网站正式允许下载。我本以为会议期间,服务器能够承受负载。由于我是会议的嘉宾,所以住在皇家套房中,房间很棒,有很漂亮的海景,但很不幸,这是唯一一间没有互联网接口的房子。更糟的是酒店没有Wi-Fi,幸好有好心的会议组织者愿意跟我换房,我才能够在普通房间内连网处理工作。

经验:专注于你真正的目标。

在有些东西看似很美好的时候,不要分心;它说不定是一个障碍。

到2005年,MINIX 3已经成为了很严肃的系统,但有很多人读过我的书,还有很多在学校里学过它,很难说服他们这个系统跟之前的“玩具”系统有巨大的不同。结果很讽刺,我有一个知名的系统,因为它之前的名声却得努力让大家认真对待它。微软很聪明,早期Windows包括95和98都只是MS-DOS,但后来他们将新系统改名为Windows。

经验:如果你的产品第三版在主要方式上与第二版不同,干脆换个新名字。

2008年,MINIX获得了另一次机会,拿到了大约350万美元的资助。

但这个巨大的机遇也创造了一个严重的问题,我雇了4个专业的开发者来开发MINIX 3,并资助了6名博士生和一些博士后推动研究。结果博士生与开发者之间出现了巨大分歧,博士生复制了MINIX 3的源码,并开始用自己的研究进行大量的修改,同时开发者忙着改进Bug,并让代码产品化。两到三年后,我们没办法将损坏的版本恢复了。

尽管我也希望将研究结果运用到产品中,但遭到了程序员的强烈抵制。因为他们已经详细优化过代码,不希望再添加很多未经测试的东西进去。只能再做很多努力,才能让小组的研究成果转为现实产品。

经验:同时做研究和开发软件产品的话,结果会很难结合。

有时研究人员与开发人员会遇到同样的问题,其中一个涉及同步通讯的使用。同步通讯从一开始就存在,也非常简单,但它与可靠性的目标相矛盾。如果客户端进程C发送消息到服务器进程S,然后C在收到回应前陷入崩溃或者无限循环,S因为无法发送回复就会挂起。这个问题是同步通讯所固有的。为了避免,我们不得不引入虚拟端点、异步通讯等等,导致简洁度大幅下降。

经验:爱因斯坦说的没错,事情应当尽可能保持简单,但不能太过简单。

他的意思是:每个人都应当追求简洁,并确保解决方案足够全面地进行工作,但不可要求太甚。这也是MINIX从最开始的指导准则。

2011年左右,为了提高产品的专注度,我们做出了两个重要的决定:第一,我们认识到要想让人们使用系统,就得有应用,因此我们从BSD中借鉴了很多内容。实际上,我们已经在容错性更高的子架构中重新部署了NetBSD的用户环境,带来的收益是:突然多了6000个可用的NetBSD包。

经验:如果你希望人们使用你的产品,那它必须有用。

第二,我们意识到想要赢过Windows、Linux、OS X等桌面系统,得打一场硬仗。所以我们将MINIX 3移植到ARM处理器上,并开始专注于高可用性的嵌入式系统。此外,很多工程师都在寻找能够嵌入新相机、电视机、数字视频录像机、路由器等其他产品的操作系统,尤其是MINIX 3可以在使用ARM Cortex-A8处理器的BeagleBone系列单片机上运行(参见图3)它们基本上都是完整的PC,零售价是50美元,而且经常被用作嵌入式系统原型。所有都是开源硬件,弄清工作原理很容易。

MINIX 30年经验教训

图3 BeagleBone组件

经验:如果在市场推广中,计划A不起作用,那么改成计划B。

回顾一下:微内核也许是实现高稳定性和自修复系统的最好方式,但令人惊讶的是,30年来MINIX微内核几乎没有增加代码。甚至有一些主要的软件组件,包括驱动和大部分调度器都被移出。想要进行颠覆性的改变,需要耗费大量的时间,举个例子,根据微软的统计,到2016年3月仍有2.5电脑运行着过时的Windows XP。

经验:我们很难改变已经根深蒂固的做事方式。

此外,现在的电脑性能如此强大,效率已经不那么重要了。例如Android是用Java编写的,比C要慢得多,但好像没人在意这一点。

另一个在MINIX中运行良好的机制就是事件驱动模型。每个服务器和驱动都包含:

MINIX 30年经验教训

这种设计使得测试和隔离Debug都很容易。

另一方面,MINIX 1的简单性限制了它的可用性,缺乏内核多线程和请求式页面调度等在256kB IBM PC上并不实用的,后来这些功能可以加进去了,但我们之前没那么做,导致现在还在买单——移植某些软件非常困难。

尽管资助暂且告一段落,MINIX项目还未结束。它就像很多其他项目一样,逐渐转向开源。


订阅2016年程序员(含iOS、Android及印刷版)请访问 http://dingyue.programmer.com.cn
MINIX 30年经验教训

订阅咨询:

• 在线咨询(QQ):2251809102
• 电话咨询:010-64351436
• 更多消息,欢迎关注“程序员编辑部