Skip to content

Latest commit

 

History

History
160 lines (84 loc) · 17.3 KB

UNIX传奇:历史与回忆.md

File metadata and controls

160 lines (84 loc) · 17.3 KB

UNIX传奇:历史与回忆

布莱恩·W.克尼汉

Unix传奇往事的启示

Unix的“分而治之”设计哲学——让每个程序做好一件事;要做一件新的工作,就构建新程序,而不是通过增加新“特性”使旧程序复杂化——被优秀程序员奉为圭臬。

文件、目录、系统调用、shell、管道,还有一大批优秀的生产力工具,如grep(正则表达式)、diff、Lex、Yacc、Make等,都凝结着Unix创造者的智慧和心血。

见证软件历史丰碑

与人类的历史相比,软件的历史很短。1843年,英国大诗人拜伦的女儿埃达•洛夫莱斯(Ada Lovelace,1815—1852)为数学家巴贝奇的分析引擎编写了一个用于计算伯努利数的程序。凭借这段程序,埃达享有了第一个程序员的美名。她编写的伯努利数程序被认为是人类历史上的第一个计算机程序。这如果算作软件历史的起点,那么距今还不到200年。

译 者 序

程序员的追求就是让机器听话,让工作自动化,让人类生活更美好。

第1章 贝尔实验室

要了解Unix是如何产生的,得先了解贝尔实验室,尤其是其运作机理,以及它提供的创意环境。

AT&T,即美国电话电报公司(American Telephone and Telegraph Company),由分布于美国各地的多个当地电话公司组合而成。在其发展历史的早期阶段,AT&T意识到,它需要一个研究机构,系统解决在建设全国电话系统时遇到的科学和工程难题。1925年,AT&T创办研发子公司贝尔电话实验室(Bell Telephone Laboratories),意在解决这些难题。该机构通常被简称为贝尔实验室(Bell Labs)或BTL,有时甚至只是“实验室”,但电话系统始终是其关注的重点。

1.1 贝尔实验室的物理科学研究

贝尔实验室雇员还发明了负反馈放大器、太阳能电池、激光器、手机、通信卫星和电荷耦合器件(有了它,手机上的摄像头才能工作)等。

持续的资金投入是研究工作的关键保障。这意味着AT&T能布局长远,贝尔实验室的研究员们也能自由探索那些未必有短期回报,甚至可能永无回报的领域。现今世界已全然不同,多数人只做未来几个月的规划,功夫都花在了预测下一季度财务状况上。

2.1 一点点技术背景知识

更加麻烦的是,操作系统用汇编语言写成。汇编语言是人能读懂的机器指令,与特定类型硬件的指令集紧密相关。每种计算机都有自己的汇编语言,所以操作系统是庞大且复杂的汇编语言程序,每个操作系统都针对特定硬件、使用特定语言编写。 系统之间缺乏共通性,使用相互不兼容的低级语言,导致同时需要多个版本的程序:为某一操作系统编写的程序,在移植到其他操作系统或硬件架构上时,必须完全重写。这种状况阻碍了进步。如后文所述,Unix操作系统在所有类型的硬件上都保持一致,而且用较高级的语言写成,只需付出相对较少的成本,即可从一种计算机移植到另一种计算机

2.3 Unix起源

正如他在2019年一次采访中所说,“一周,一周,再一周,我们就有了Unix。”无论以何种方式来度量,这都体现了真正的软件生产力。

3.3 Unix程序员手册

cat命令50年来没有变过,只添加了很少的可选(也许并不必要的)参数,修改了其操作行为,它仍然是Unix核心命令之一。

3.4 存储略谈

内存往往是计算机中最昂贵的部件。每个字节都很珍贵。程序员受内存资源约束,得随时清楚使用了多少内存,有时不得不采取讨巧和冒险的编程技术来将程序放入可用内存中。

当程序出现严重错误时,操作系统会注意到,并试图通过创建一个保存主存储器状况(即磁芯中的内容)的文件来帮程序员定位错误,这就是“磁芯转储”(core dump)一词的由来。虽然磁芯早已退出舞台,这个词仍在使用。保存主存储器状态的文件仍然被称为磁芯(core)。

3.5 丹尼斯·里奇小传

“本科经历告诉我,我不够聪明,成不了物理学家,那时我也认识到计算机有多厉害。研究生经历令我确信,我不够聪明,成不了算法理论专家。我也认识到,自己更喜欢过程式语言而不是函数式语言。” 就像C++的创造者本贾尼·斯特劳斯特鲁普曾说过的那样,“如果丹尼斯决定把那10年的时间花在研究深奥的数学上,Unix就会‘胎死腹中’。”

有了C语言,就有可能使用高级语言编写整个操作系统。到了1973年,Unix已经从原来的汇编语言改为C语言编写,系统的维护和修改变得更加容易。将操作系统从最初的PDP-11计算机移植到其他不同架构的计算机,这是C语言带来的另一个巨大进步。由于大部分系统代码都用C语言编写,所以移植系统所需工作并不比移植C语言编译器多多少。

4.4 管道

管道符号是两个命令之间的一道竖杠,简单而优雅。例如,要计算某个目录中的文件数量,可以将ls的输出(每个文件一行)用管道导向wc(计算行数)的输入。 $ ls | wc 不妨将程序看成一种过滤器,读取数据进来,以某种方式进行处理,然后输出结果。

但由于分时的本质是多人共享同一台计算机,所以知道还有谁也在使用系统会很有帮助。who命令确实增加了社群感:你可以看到谁登录了系统。遇到问题时,即使大家都是深夜在家工作,也可以寻求对方帮助。

4.5 grep命令

grep这个名字来自ed文本编辑器中的命令g/re/p,它列出所有符合正则表达式模式re的行,《牛津英语词典》中grep的条目(图4-2)释义正确。

5.2 Yacc,Lex,Make

创建了编译器-编译器YACC(下文写作Yacc)。这个名字源于杰夫·厄尔曼的评论意见,它代表“yet another compiler-compiler”(意为“又一个编译器-编译器”),说明它并不是第一个这种程序。

5.4 sed和awk

今天,sed在shell脚本中经常被用于以某种方式转换数据流:替换字符,添加或删除不需要的空格,或丢弃不需要的东西。

李经历非凡——他是哈佛大学的心理学博士,曾在耶稣会神学院学习,准备成为神职人员,后来却踏上了更世俗化的计算机科学家之路。他是Unix小组中最早思考大规模处理文本的人之一,而当时主存储器还处于小到根本无法存储大量文本的阶段。多说一句,“大量”是相对而言。李在20世纪70年代初对《联邦论:美国宪法述评》(Federalist Papers)特别感兴趣,文集中所有文章加起来总共只有1 MB多一点。

作为被高频使用的shell管道组件,sed广受欢迎。我甚至有一张保险杠贴纸,印着 “Sed and awk: together we can change everything.”[12]

6.2 高校授权

6.2 高校授权 1973年,AT&T开始向高校发放Unix许可,只收取象征性的费用,不过大多数许可都针对1975年推出的第6版。也卖出一些第6版商业许可,索价高达2万美元,大概等于今时今日的10万美元。许可包括所有源代码,但不提供任何支持。

加利福尼亚大学伯克利分校是最活跃的许可获得者之一,该校的一些研究生对系统做出了重大贡献,最终演化出伯克利软件发行版(Berkeley Software Distribution,BSD)。BSD是由最初的科研版Unix演变而来的两个主要分支之一。

1975年和1976年,肯·汤普森在伯克利度过了一个休假年,教授操作系统课程。有个叫比尔·乔伊(Bill Joy)的研究生(图6-2)修改Unix的本地版本,添加了一些自己的程序,包括vi文本编辑器(现在仍然是最流行的Unix编辑器之一)和csh(C语言shell)。比尔后来为Unix设计了至今仍在使用的TCP/IP网络接口。有了他的socket接口,就能用与文件和设备I/O相同的读写系统调用来读写网络连接,因此很容易添加网络功能。

比尔的编辑器使用光标寻址来更新屏幕上正在编辑的文本,这是对行编辑模式的重大改变:将光标移到this一词所在位置(也许是使用正则表达式),输入cw(change word,意为“改字”)这样的命令,然后再输入that,this立即就换成了that。

我忘了当时给出何等评价(尽管今天vi是我最常用的两个编辑器之一),只记得我告诉比尔,他应该停止折腾编辑器,专心完成他的博士学位。他没有理会我的建议,这对大家都是一件幸事。几年后,他从研究生院退学,与人共同创办了工作站先驱Sun微系统(Sun Microsystems)公司,公司的工作站软件基于伯克利Unix,其中就包括比尔在系统、网络和工具方面的基础研发成果(以及他的vi编辑器)。当学生向我寻求职业建议时,我经常引用这个故事——有“智”不在年高。

8.1 伯克利软件发行版

SunOS在早期伯克利版本基础上发展而来,被用在由比尔·乔伊共同创办的Sun微系统公司的计算机上。其他发行版在几年后分离出来,形成了上述BSD变种。所有这些版本归根结底都是对Unix的重新实现,虽然提供相同功能,但使用了全新代码。一旦重新编写,它们就不包含AT&T的代码,不会侵犯AT&T的知识产权。

虽然NeXT计算机公司本身未能取得商业成功,但1997年该公司被苹果公司收购,乔布斯也随之回归,并在一年内重任首席执行官。在Objective-C程序中,人们仍然可以从NSObject和NSString等名称上看到NextSTEP操作系统的遗留影响。

8.2 Unix战争

1992年,USL和AT&T就侵犯Unix知识产权为由起诉伯克利,声称伯克利未经许可使用AT&T的代码。伯克利对AT&T的代码做了大量修改,并增加了许多有价值的内容,包括令人们能够访问互联网的TCP/IP代码。

回过头来看,我想可以说,AT&T早期几乎是偶然地决定向高校提供Unix,导致了所有这些法律纠纷。随着Unix从免费使用的高校传播到愿意付费的公司,它在商业上变得可行,至少是可能可行。但时机已过,无法进行有效保护。即使AT&T的源代码受到保护,系统调用接口实际上也是在公共领域,而且社区中存在着大量的专业人士,创建不受AT&T许可约束的版本几乎是手到擒来。编译器、编辑器和所有工具等应用软件也是如此。皇冠上的珠宝不翼而飞后,AT&T才想起来去锁谷仓大门,为时已晚。

8.3 Minix和Linux

AT&T试图从软件中赚钱,对Unix的许可限制越来越多,其中也包括高校如何使用Unix的限制。BSD没有这种限制,优势顿显。同时,AT&T和BSD之间争斗不断,也推动其他人试着推出自己的类Unix系统。独立创建的版本不受

一位21岁的芬兰大学生,不满AT&T限制性许可,受Minix鼓舞,独立开发出一套类Unix系统,在系统调用层面上兼容Unix。1991年8月25日,林纳斯·托瓦兹(Linus Torvalds)在Usenet新闻组comp.os.minix上发布了一个项目,如图8-3所示。

目前我已经移植了bash(1.08)和gcc(1.40),看来一切正常。这意味着我将在几个月内得到一些实用的东西,我想知道大多数人想要什么功能。欢迎任何建议,但我不会保证我会实现它们。:-) 林纳斯(torv...@kruuna.helsinki.fi

8.4 Plan 9

不过,Plan 9确实为世界贡献了一件无比重要的东西:Unicode的UTF-8编码。

肯·汤普森和罗布·派克为这个问题头疼,因为他们决定Plan 9将全程使用Unicode而非ASCII。1992年9月,他们提出UTF-8方案。UTF-8是一种巧妙的Unicode可变长度编码,在空间和处理时间上都很有效率。它将每个ASCII字符表示为单个字节,而其他字符只使用2个或3个字节,最多不超过4个字节。编码紧凑,而且ASCII成了天然合规的UTF-8。UTF-8可以边读取边解码,因为没有任何合法字符是其他字符的前缀,也没有任何字符是其他字符或字符序列的一部分。今天互联网上几乎所有的文本都用UTF-8编码,遍处皆是,人人使用。

第9章 遗产

贝尔实验室为Unix开发的语言和工具随处可见。在这些编程语言中,有C语言和C++,它们至今仍是系统编程的中流砥柱,还有如awk和AMPL等更专门的语言。核心工具有shell、diff、grep、Make和Yacc等。

GNU(“GNU’s not Unix”的递归缩写[1])是一个大型软件集合,大部分基于Unix模式,以源代码的形式免费提供给所有人使用:有了它,Unix上几乎所有东西都可以使用,甚至包括更多工具。GNU加上Linux操作系统,相当于免费版的Unix。Unix命令的GNU实现是开源的,可以被使用和扩展。唯一的限制是,如果发布了改进,成果必须免费提供给每个人,不可以私有。当今大量的软件开发都基于开源项目,在很多情况下就是基于GNU的实现。

9.1 技术方面

分层文件系统是对既有做法的重大简化,尽管事后看来,它显而易见——你还会想要什么?Unix文件系统提供直截了当的视角:从根目录开始,每个目录要么包含文件的信息,要么包含容纳更多目录和文件的目录信息,而不是由操作系统来管理不同类型文件的属性,也不限制文件在目录中嵌套的深度。文件名只是从根目录开始的路径,各组成部分用斜线隔开。

文件的创建、读取、写入和删除只需六七个系统调用即可完成。屈指可数的权限位定义了访问控制,能够满足大多数目的。像可移动磁盘这样的存储设备可以挂载在文件系统上,从逻辑上讲,就成了文件系统的一部分。

管道是典型的Unix发明,是临时连接程序的一种优雅而高效的方式。让数据流过一系列处理步骤,又自然又直观;语法异常简单;管道机制与小工具集合完美契合。当然,管道并不能解决所有的连接问题,但道格·麦基尔罗伊最初概念中完全通用的非线性连接在实践中并不经常出现,线性管道几乎总是足敷使用。

将程序当作工具并组合使用是Unix的特色。编写各自做好一件事的小程序,而不是功能繁多的单个大程序,有很多好处。当然,有些时候单体程序有其意义,但能让普通用户以新奇方式组合使用的小程序集合优势明显。

普通文本是标准数据格式。文本的普遍使用是一种极大的简化。程序读取字节,如果它们的目的是处理文本,那么这些字节将采用标准表示方式,通常是长短不一的行,每行均以换行符结束。这种做法并非万能,但几近普适,且不必付出太多空间或时间代价。因此,所有这些小工具单独使用或组合起来,就能处理任何数据。

shell就是好例子:它是用来运行程序的,而且它在这方面非常擅长,但你不会想用它来写浏览器或视频游戏。当然,专业化是古老的概念,最早的高级语言都是针对特定目标的,如Fortran针对科学和工程计算,COBOL针对商业数据处理。妄图“上下通吃”的“语言先烈”也不罕见,PL/I就是其中之一。

(i)让每个程序做好一件事。要做一件新的工作,就构建新程序,而不是通过增加新“特性”使旧程序复杂化。

(ii)预期每个程序的输出都能成为另一个未知程序的输入。不要用无关的信息来干扰输出。避免使用严格的分栏对齐或二进制输入格式。不要执着于交互式输入。

(iii)设计和构建软件,甚至是操作系统,要尽早试用,最好是在几周内就用起来。大刀阔斧砍掉笨拙的部件,重建它们。

9.2 组织

聘请优才。慎于雇人。在1127中心通常每年只能新雇一两人,而且几乎都是年轻人,所以招聘决策非常谨慎,也许是过于谨慎了。当然,这也是高校熟悉的问题:人们往往不清楚该招专才还是通才。正如史蒂夫·约翰逊所说,我们应该雇用运动员还是一垒手[4]?我的首选是那些术有专攻的人,至于具体什么专业领域倒在其次。

人们把食品留在Unix房间里,供大家享用。有人曾经留下一大袋10千克的优质巧克力,让大家分着吃。但不总有这么高规格的食物: “有人带了一袋贴着中文标签的物品来。大家都咬了一口,然后就放弃了。后来,我们发现它越变越少:一定是哪个家伙在偷吃。袋子快见底时,有位懂中文的人告诉我们,袋子上的说明写着,在开水中浸泡一小时后食用。” 可是,如今人们对这种常见的团队建设活动的热情很低,很多人认为,这些活动矫揉造作、毫无意义,纯属浪费时间。

9.3 认可

“Unix也是互联网发展的主要推动力。加利福尼亚大学伯克利分校开发了伯克利软件发行版(BSD),这是Unix的扩展版本,与互联网协议套件TCP/IP一起实现。BSD的开发基于贝尔实验室在1975年连同其源代码一起分发给高校和研究机构的Unix第6版,这是开源文化的肇始。BSD Unix帮助实现了互联网。”