读UNIX传奇:历史与回忆03第6版

读UNIX传奇:历史与回忆03第6版

1. 第6版

1.1. 第1版Unix在1971年底开始运行

1.2. 第6版Unix,其手册发布于1975年5月,首次拓展到贝尔实验室以外

1.3. 丹尼斯·里奇和肯·汤普森的论文“The Unix Time-Sharing System”​(Unix分时系统)首次公开描述了Unix

  • 1.3.1. 发表在1973年10月举行的第四届ACM操作系统原理研讨会(ACM Symposium on Operating Systems Principles)上

  • 1.3.2. 1974年7月,稍做修改后,这篇论文重新发表在《ACM通讯》​(Communications of the ACM,CACM)上

1.4. Unix是一个通用、多用户、交互式操作系统,运行在数字设备公司PDP-11/40和11/45计算机上

  • 1.4.1. 包含可拆卸卷的分层文件系统

  • 1.4.2. 可兼容的文件、设备和进程间I/O(输入/输出)

  • 1.4.3. 初始化异步进程的能力

  • 1.4.4. 每个用户可选择不同的系统命令语言

  • 1.4.5. 100多个子系统,包括十几种语言

2. 文件系统

2.1. 文件系统是操作系统的一部分,负责管理磁盘等次级存储设备上的信息

2.2. 磁盘是基于磁性旋转介质的精密机械装置,如今最常见的是固态硬盘和USB闪存盘等没有可移动部件的集成电路

  • 2.2.1. 通过Windows上的资源管理器(Explorer)和macOS上的访达(Finder)等程序

2.3. 在Multics之前,大多数操作系统充其量只是提供了复杂又不规则的文件系统来存储信息

2.4. Multics文件系统比当时的其他文件系统更通用、更规则、更强大,但相应地也很复杂

2.5. 每个Unix文件都只是一系列字节的组合

  • 2.5.1. 文件内容的结构或组织方式只由处理它的程序决定,文件系统本身并不关心文件中的内容

  • 2.5.2. 意味着任何程序都可以读取或写入任何文件

2.6. Unix没做区分:任何程序都可以处理任何文件

  • 2.6.1. 如果程序处理不了文件,例如,试图将Fortran源文件当作C语言程序来编译,那和操作系统没有任何关系

2.7. Unix以目录为单位来组织文件

  • 2.7.1. Unix目录也是文件系统中的一个文件,但其内容由系统本身维护,不由用户程序维护

  • 2.7.2. 目录中包含了其下文件的信息,而这些文件又可以是目录

  • 2.7.3. Unix目录项包括目录内的文件名、访问权限、文件大小、创建和修改的日期及时间,以及在哪里可以找到文件内容的信息

  • 2.7.4. 目录可以包含子目录,所以文件系统可以深入至任意层

  • 2.7.4.1. 嵌套目录和文件的组织方式被称为“分层”文件系统

  • 2.7.4.2. 有些文件系统限制了嵌套的深度,CTSS就限制只能有两层

3. 系统调用

3.1. 操作系统为运行于其上的程序提供一系列服务,包括启动和停止程序、读取或写入文件中的信息、访问设备和网络连接、报告日期和时间之类信息等

3.2. 系统调用就是操作系统,因为它们定义了系统提供的服务

  • 3.2.1. 一套系统调用可能有多个独立的实现,Unix系统和类Unix系统的不同版本就是如此

3.3. 第1版Unix只有30多个系统调用,其中大约一半与文件系统有关

  • 3.3.1. 由于文件只包含未经释义的字节,所以基本的文件系统接口非常简单,只有5个系统调用,用于打开或创建文件,读写其字节,以及关闭文件

3.4. 调用open和creat产生的fd值称为文件描述符(file descriptor)​,是一个非负小整数,在后续的文件读写中使用

3.5. creat系统调用之所以这么拼写,只能归咎于肯 · 汤普森的个人品位,没有其他什么好借口

3.6. Unix的另一创新是把磁盘、终端等外围设备都看作文件系统中的文件,磁盘是功能列表中提到的“可拆卸卷”​

3.7. 真实的设备有奇怪的属性要处理,所以还有其他系统调用来处理这些特殊性,尤其是终端的特殊性

3.8. 50年来,这些系统调用都得到了完善,偶尔也有改进,但基本模式很简单,易于使用

3.9. 早期操作系统中,真实设备的所有复杂情况都会反馈给用户

3.10. 文件只是字节

  • 3.10.1. 用户决定这些字节代表什么,而操作系统则只负责存储和取出,不向用户暴露设备属性

4. shell

4.1. shell是运行其他程序的程序

  • 4.1.1. Unix shell最重要的功能是运行程序

  • 4.1.2. 它让用户运行命令,是用户和操作系统之间的主要接口

4.2. shell是个普通的用户程序,而非操作系统的组成部分,这也是从Multics中汲取的概念

4.3. shell是用户程序,所以很容易用其他程序取代,这就是为什么有那么多Unix shell的原因

  • 4.3.1. 所有Unix shell都提供了相同的基本功能,通常也采用相同的语法

4.4. shell的另一主要服务是I/O重定向

  • 4.4.1. 如果目标文件尚不存在,就会被创建

  • 4.4.2. 一种统一机制,由shell应用,而不是由单独的程序应用,并且比通过文件名参数指定文件输入和输出的方法更容易使用

4.5. shell脚本(shell script)是存储在文件中的一系列命令

  • 4.5.1. 用该文件作为输入源,运行shell实例

4.6. 使shell程序完全等同于编译后的程序的最后一步:如果文件被标记为可执行文件,它将被传递给shell执行

4.7. shell脚本并不能取代编译后的程序,但它们是程序员工具箱的重要组成部分,既适用于个人,也适用于大型任务

  • 4.7.1. 如果你发现自己一遍又一遍地运行着同样的命令序列,那就把它们放到shell脚本中,从而将烦琐工作变得自动化

  • 4.7.2. 如果某个shell脚本太慢,可以用其他语言重写

5. 管道

5.1. 管道是Unix中最引人注目的创新

  • 5.1.1. 管道是Unix的主要贡献之一

5.2. 管道是一种机制,由操作系统提供,并通过shell轻松访问

5.3. 将程序的输出与另一程序的输入连接起来

5.4. 只需要一个既简单又自然的shell符号就能用起来,结果是得到一种设计和使用程序的新思路

5.5. 管道是“超级小菜”​,因为I/O重定向的机制早已存在了

5.6. 管道符号是两个命令之间的一道竖杠,简单而优雅

5.7. 标准错误是独立的输出流:发送给它的错误信息被区隔在标准输出之外,因此不会进入管道

  • 5.7.1. 大多数程序只需要抛弃会扰乱管道的无关信息,并将错误报告发送到stderr即可

5.8. 管道面世的确切日期没人记得,不过应该是在1972年下半年,因为它没有出现在手册的第2版(1972年6月)​,但在第3版(1973年2月)中出现了

6. grep命令

6.1. Unix生来就是命令行系统,也就是说,用户通过输入命令来运行程序,而不是像Windows或macOS那样通过鼠标指向和点击图标来运行程序

6.2. 对于新手来说,命令行界面并不如指向和点击那样简单,但即使在只有中度经验的人手中,它也会高效得多

6.3. 能实现图形界面无法实现的自动化功能:命令序列可以从脚本中运行,输入单个指令就能作用于大量文件

6.4. 一向拥有丰富的命令行小工具,也就是处理日常简单任务的程序

6.5. 要想用好Unix,和学习自然语言一样,必须学习类似于不规则动词族系的东西

6.6. grep这个名字来自ed文本编辑器中的命令g/re/p,它列出所有符合正则表达式模式re的行

6.7. 每行一个—单引号之间的神秘字符串是一个正则表达式,或谓模式

6.8. grep源自ed,所以它的正则表达式用法和ed中的一样

7. 正则表达式

7.1. 正则表达式是一种用于指定文本模式的符号

  • 7.1.1. 可以是单词,如expression

  • 7.1.2. 可以是短语,如regular expression

  • 7.1.3. 可以是更复杂的文本

7.2. 正则表达式就是一种描述文本模式的小型语言

  • 7.2.1. 单词或短语本身就是正则表达式,它在文本中代表自己,正则表达式识别器会找到它出现的每处地方

7.3. Unix对正则表达式的“痴恋”由来已久,正则表达式遍布于文本编辑器、grep及其衍生工具以及许多其他语言和工具中

7.4. 对于大多数任务而言,QED都过于强悍了

7.5. ed比QED简单得多,但它也支持正则表达式

7.6. 最早的实现方式是由shell调用名为glob(代表“global”​,意为“全局”​)的独立程序

  • 7.6.1. 从模式中生成文件名扩展列表的操作被称为“globbing”​

  • 7.6.2. glob这个名字如今在Python等几种编程语言的库中仍然存在

7.7. 阿尔·阿霍对Unix的早期贡献之一是扩展了grep,让它能支持更丰富的正则表达式,例如可以搜索像this|that这样的替代模式

  • 7.7.1. 把这个程序称为egrep,表示“extended grep”​(意为“扩展grep”​)

8. C语言

8.1. 新编程语言一直是Unix的重要组成部分

8.2. Multics尝试用高级语言PL/I来编写操作系统,这是其一大贡献

8.3. IBM于1964年创建PL/I,意图融合Fortran、COBOL和ALGOL的全部优点

  • 8.3.1. PL/I成了第二系统效应的范例

8.4. 道格·麦基尔罗伊和道格·伊斯特伍德(Doug Eastwood)临时救急,创造了在Multics上使用的PL/I简化子集,称为EPL(​“Early PL/I”​,早期PL/I)​,但EPL仍然是一种复杂的语言

8.5. BCPL(Basic Combined Programming Language,基本组合编程语言)是另一种用于系统级编程的语言

  • 8.5.1. 由剑桥大学教授马丁·理查兹(Martin Richards)设计

  • 8.5.2. 理查兹1967年访问麻省理工学院时为它写了编译器

  • 8.5.3. BCPL比PL/I的任何分支版本都简单得多,很适合编写操作系统代码

  • 8.5.4. 贝尔实验室Multics开发组成员们非常熟悉BCPL

8.6. 肯不断重新设计,最终打造出满足PDP-7条件限制的语言

  • 8.6.1. 这种语言更接近于BCPL而不是Fortran,肯叫它B语言

  • 8.6.1.1. B语言很适合PDP-7这样以字为操作单位的计算机

  • 8.6.1.2. 不适合PDP-11这样以字节为操作单位的计算机

8.7. 面向字的计算机在单独或按顺序处理字节时很笨拙

  • 8.7.1. 程序员必须使用库函数或通过特别的编程技巧来访问装在较大块中的单个字节

8.8. PDP-11以字节为操作单位:它主存储器的基本单位是8位字节,而不是早期计算机的18位或36位字长

  • 8.8.1. 可以处理较大块的信息,如16位和32位整数以及16位地址

8.9. PDP-11到货后,丹尼斯开始针对新的架构对B语言进行增强,并为其编写编译器

  • 8.9.1. 新的语言被称为“NB”​,即“New B”​(意为“新B语言”​)​,最后发展成了C语言

8.10. B语言与C语言主要区别之一是,B语言无类型,而C语言则支持与PDP-11提供的数据类型相匹配的数据类型:1字节、2字节的整数,以及4字节或8字节的浮点数

8.11. C语言支持对类型指针的算术运算,这是对编程语言的新颖贡献

  • 8.11.1. 指针是内存地址的值,标记主存储器中的某个位置

  • 8.11.2. 指针的类型即它指向对象的类型

8.12. Unix应该从汇编语言转换为更高层级的语言,而C语言正是上上之选

  • 8.12.1. 肯在1973年曾3次尝试用C语言编写内核,但直到丹尼斯在语言中加入了定义和处理嵌套数据结构的机制(struct)才得以实现

  • 8.12.2. C语言已经有足够的表现力来编写操作系统代码,Unix也就成了主要用C语言编写的程序

  • 8.12.3. 第6版内核有大约9000行C语言代码和大约700行汇编语言代码

  • 8.12.4. 汇编代码用于设置寄存器、设备和内存映射等与特定机型相关的操作

8.13. 1989年,ANSI和ISO完成了第一份C语言正式标准

  • 8.13.1. 这份标准对语言的描述直接基于丹尼斯的参考手册

8.14. C语言很重要,但它对标准库的使用也很重要

  • 8.14.1. 标准库为程序员提供了进行格式化输入和输出、字符串处理和数学函数等操作所需的基础能力

  • 8.14.2. 最大的库组件提供了格式化输出能力

  • 8.14.3. 迈克尔·莱斯克的可移植I/O包写于1972年,目的是让程序能够很容易地移植到Unix,或从Unix移植到其他系统

  • 8.14.3.1. 它包含了printf的首个版本,以及用于解析格式化输入的scanf

  • 8.14.3.2. C语言的printf函数已经为许多其他语言所采用,每位程序员都对它耳熟能详

9. 软件工具

9.1. 到1975年中至年末,Unix已在各种会议和期刊论文中公开露面,第6版在大约一百所高校和数量有限的商业机构中得到使用

9.2. 技术界仍主要使用Fortran,运行环境是硬件提供商的操作系统,如IBM的System/360

9.3. 墨里山的大多数程序员使用GE 635,运行GE的批处理操作系统GECOS

  • 9.3.1. 1970年,GE将其计算机业务出售给霍尼韦尔,GECOS更名为GCOS

9.4. Ratfor,代表“rational Fortran”​(意为“理性Fortran”​)

  • 9.4.1. Ratfor将C语言的控制流程,包括if-else、for、while和用于分组的括号,转换成Fortran的IF和GOTO语句,以及DO循环结构

9.5. Ratfor是第一个以C语言为基础语法的语言

  • 9.5.1. 用Ratfor编写Fortran代码,比编写标准Fortran代码愉快得多

9.6. 布伦达·贝克(Brenda Baker)写了一个名为struct的程序,它能将任意Fortran程序翻译成Ratfor程序

  • 9.6.1. 布伦达的程序既有理论高度,又是实践力作,它证明了几乎任何Fortran程序都可以拥有良好的结构形式

  • 9.6.2. 借助Ratfor,就能以独一无二的最佳方式来呈现它

  • 9.6.3. 使用struct 的人发现,Ratfor版本几乎总是比他们最初编写的Fortran代码更有条理

9.7. Pascal作为一种教学语言在高校里很受欢迎

  • 9.7.1. Pascal有很好的特性,包括合理的控制流

10. 道格·麦基尔罗伊

10.1. 罗布·派克称道格·麦基尔罗伊为“Unix的无名英雄”

10.2. 道格1954年在康奈尔大学获得物理学本科学位,1959年在麻省理工学院获得应用数学博士学位

10.3. 道格早期在PL/I和EPL上的语言方面工作

10.4. Unix一经问世,他就写出各种各样的基础软件

  • 10.4.1. 他写的存储分配器malloc用了很多年

  • 10.4.2. 他对分配器的研究影响深远

  • 10.4.3. 列出了spell、diff、sort、join、graph、speak、tr、tsort、calendar、echo和tee

  • 10.4.3.1. 有些是小工具,如echo

  • 10.4.3.2. 有些是大工具,如sort和diff

  • 10.4.4. 大多数都是Unix计算的核心工具,其中很多沿用至今

10.5. 管道也来自他的构想,不过最终版本采用了肯的语法

  • 10.5.1. 管道之所以能出现,全拜道格不遗余力地游说所赐

10.6. diff程序是说明好理论如何与好实践工程相结合,打造出基本工具的又一范例

10.7. 道格通常是论文或手册草稿的第一位读者,他巧妙地戳破修辞气球,删繁就简,剔除不必要的副词

  • 10.7.1. 他完善和打磨了Unix命令手册,整理和组织了Unix第8版到第10版的手册内容
posted @ 2026-06-15 06:16  躺柒  阅读(10)  评论(0)    收藏  举报