操作系统开发:计算之神的几次重大突破

发表时间: 2019-12-10 17:00

早期操作系统:只是一些库

一开始,操作系统并没有做太多事情。基本上,它只是一组常用函数库。例如,不是让系统中的每个程序员都编写低级I/O处理代码,而是让“OS”提供这样的API,这样开发人员的工作更加轻松。

通常,在这些老的大型机系统上,一次运行一个程序,由操作员来控制。这个操作员完成了你认为现代操作系统会做的许多事情(例如,决定运行作业的顺序)。如果你是一个聪明的开发人员,就会对这个操作员很好,这样他们可以将你的工作移动到队列的前端。

这种计算模式被称为批(batch)处理,先把一些工作准备好,然后由操作员以“分批”的方式运行。此时,计算机并没有以交互的方式使用,因为这样做成本太高:让用户坐在计算机前使用它,大部分时间它都会闲置,所以会导致设施每小时浪费数千美元[BH00]。

超越库:保护

在超越常用服务的简单库的发展过程中,操作系统在管理机器方面扮演着更为重要的角色。其中一个重要方面是意识到代表操作系统运行的代码是特殊的。它控制了设备,因此对待它的方式应该与对待正常应用程序代码的方式不同。为什么这样?好吧,想象一下,假设允许任何应用程序从磁盘上的任何地方读取。因为任何程序都可以读取任何文件,所以隐私的概念消失了。因此,将一个文件系统(file system)(管理你的文件)实现为一个库是没有意义的。实际上,还需要别的东西。

因此,系统调用(system call)的概念诞生了,它是Atlas计算系统[K+61,L78]率先采用的。不是将操作系统例程作为一个库来提供(你只需创建一个过程调用(procedure call)来访问它们),这里的想法是添加一些特殊的硬件指令和硬件状态,让向操作系统过渡变为更正式的、受控的过程。

系统调用和过程调用之间的关键区别在于,系统调用将控制转移(跳转)到OS中,同时提高硬件特权级别(hardware privilege level)。用户应用程序以所谓的用户模式(user mode)运行,这意味着硬件限制了应用程序的功能。例如,以用户模式运行的应用程序通常不能发起对磁盘的I/O请求,不能访问任何物理内存页或在网络上发送数据包。在发起系统调用时 [通常通过一个称为陷阱(trap)的特殊硬件指令],硬件将控制转移到预先指定的陷阱处理程序(trap handler)(即预先设置的操作系统),并同时将特权级别提升到内核模式(kernel mode)。在内核模式下,操作系统可以完全访问系统的硬件,因此可以执行诸如发起I/O请求或为程序提供更多内存等功能。当操作系统完成请求的服务时,它通过特殊的陷阱返回(return-from-trap)指令将控制权交还给用户,该指令返回到用户模式,同时将控制权交还给应用程序,回到应用离开的地方。

多道程序时代

操作系统的真正兴起在大主机计算时代之后,即小型机(minicomputer)时代。像数字设备公司(DEC)的PDP系列这样的经典机器,让计算机变得更加实惠。因此,不再是每个大型组织拥有一台主机,而是组织内的一小群人可能拥有自己的计算机。毫不奇怪,这种成本下降的主要影响之一是开发者活动的增加。更聪明的人接触到计算机,从而让计算机系统做出更有趣和漂亮的事情。

特别是,由于希望更好地利用机器资源,多道程序(multiprogramming)变得很普遍。操作系统不是一次只运行一项作业,而是将大量作业加载到内存中并在它们之间快速切换,从而提高CPU利用率。这种切换非常重要,因为I/O设备很慢。在处理I/O时让程序占着CPU,浪费了CPU时间。那么,为什么不切换到另一份工作并运行一段时间?

在I/O进行和任务中断时,要支持多道程序和重叠运行。这一愿望迫使操作系统创新,沿着多个方向进行概念发展。内存保护(memory protection)等问题变得重要。我们不希望一个程序能够访问另一个程序的内存。了解如何处理多道程序引入的并发(concurrency)问题也很关键。在中断存在的情况下,确保操作系统正常运行是一个很大的挑战。我们将在本书后面研究这些问题和相关主题。

当时主要的实际进展之一是引入了UNIX操作系统,主要归功于贝尔实验室(电话公司)的Ken Thompson和Dennis Ritchie。UNIX从不同的操作系统获得了许多好的想法(特别是来自Multics [O72],还有一些来自TENEX [B+72]和Berkeley分时系统[S+68]等系统),但让它们更简单易用。很快,这个团队就向世界各地的人们发送含有UNIX源代码的磁带,其中许多人随后参与并添加到系统中。

摩登时代

除了小型计算机之外,还有一种新型机器,便宜,速度更快,而且适用于大众:今天我们称之为个人计算机(Personal Computer,PC)。在苹果公司早期的机器(如Apple II)和IBM PC的引领下,这种新机器很快就成为计算的主导力量,因为它们的低成本让每个桌子上都有一台机器,而不是每个工作小组共享一台小型机。

遗憾的是,对于操作系统来说,个人计算机起初代表了一次巨大的倒退,因为早期的系统忘记了(或从未知道)小型机时代的经验教训。例如,早期的操作系统,如DOS(来自微软的磁盘操作系统),并不认为内存保护很重要。因此,恶意程序(或者只是一个编程不好的应用程序)可能会在整个内存中乱写乱七八糟的东西。第一代macOS(V9及更早版本)采取合作的方式进行作业调度。因此,意外陷入无限循环的线程可能会占用整个系统,从而导致重新启动。这一代系统中遗漏的操作系统功能造成的痛苦列表很长,太长了,因此无法在此进行全面的讨论。

幸运的是,经过一段时间的苦难后,小型计算机操作系统的老功能开始进入台式机。例如,macOS X的核心是 UNIX,包括人们期望从这样一个成熟系统中获得的所有功能。Windows在计算历史中同样采用了许多伟大的思想,特别是从Windows NT开始,这是微软操作系统技术的一次巨大飞跃。即使在今天的手机上运行的操作系统(如Linux),也更像小型机在20世纪70年代运行的,而不像20世纪80年代PC运行的那种操作系统。很高兴看到在操作系统开发鼎盛时期出现的好想法已经进入现代世界。更好的是,这些想法不断发展,为用户和应用程序提供更多功能,让现代系统更加完善。

UNIX的重要性

在操作系统的历史中,UNIX的重要性举足轻重。受早期系统(特别是MIT著名的Multics系统)的影响,UNIX汇集了许多了不起的思想,创造了既简单又强大的系统。

最初的“贝尔实验室”UNIX的基础是统一的原则,即构建小而强大的程序,这些程序可以连接在一起形成更大的工作流。在你输入命令的地方,shell提供了诸如管道(pipe)之类的原语,来支持这样的元(meta-level)编程,因此很容易将程序串起来完成更大的任务。例如,要查找文本文件中包含单词“foo” 的行,然后要计算存在多少行,请键入:grep foo file.txt | wc -l,从而使用grep和wc (单词计数)程序来实现你的任务。

UNIX环境对于程序员和开发人员都很友好,并为新的C编程语言提供了编译器。程序员很容易编写自己的程序并分享它们,这使得UNIX非常受欢迎。作为开放源码软件(open-source software)的早期形式,作者向所有请求的人免费提供副本,这可能帮助很大。

代码的可得性和可读性也非常重要。用C语言编写的美丽的小内核吸引其他人摆弄内核,添加新的、很酷的功能。例如,由Bill Joy领导的伯克利创业团队发布了一个非常棒的发行版(Berkeley Systems Distribution,BSD),该发行版拥有先进的虚拟内存、文件系统和网络子系统。Joy后来与朋友共同创立了Sun Microsystems。

遗憾的是,随着公司试图维护其所有权和利润,UNIX的传播速度有所放慢,这是律师参与其中的不幸(但常见的)结果。许多公司都有自己的变种:Sun Microsystems的SunOS、IBM的AIX、HP的HPUX(又名H-Pucks)以及SGI的IRIX。AT&T/贝尔实验室和这些其他厂商之间的法律纠纷给UNIX带来了阴影,许多人想知道它是否能够存活下来,尤其是Windows推出后并占领了大部分PC市场……

然后出现了Linux

幸运的是,对于UNIX来说,一位名叫Linus Torvalds的年轻芬兰黑客决定编写他自己的UNIX版本,该版本严重依赖最初系统背后的原则和思想,但没有借用原来的代码集,从而避免了合法性问题。他征集了世界各地许多其他人的帮助,不久,Linux就诞生了(同时也开启了现代开源软件运动)。

随着互联网时代的到来,大多数公司(如谷歌、亚马逊、Facebook和其他公司)选择运行Linux,因为它是免费的,可以随时修改以适应他们的需求。事实上,如果不存在这样一个系统,很难想象这些新公司的成功。随着智能手机成为占主导地位的面向用户的平台,出于许多相同的原因,Linux也在那里找到了用武之地(通过Android)。史蒂夫·乔布斯将他的基于UNIX的NeXTStep操作环境带到了苹果公司,从而使得UNIX在台式机上非常流行(尽管很多苹果技术用户可能都不知道这一事实)。因此,UNIX今天比以往任何时候都更加重要。如果你相信有计算之神,那么应该感谢这个美妙的结果。

本文摘自《操作系统导论》,被认为是最适合入门学习操作系统的经典教材。

作者: [美] 雷姆兹·H.阿帕希杜塞尔、[美]安德莉亚·C.阿帕希杜塞尔 译者:王海鹏

这是一本关于现代操作系统的书。全书围绕虚拟化并发持久性这3个主要概念展开,介绍了所有现代系统的主要组件(包括调度、虚拟内存管理、磁盘和I/O子系统、文件系统 )。全书共50章,分为3个部分,分别讲述虚拟化、并发和持久性的相关内容。本书大部分章节均先提出特定的问题,然后通过书中介绍的技术、算法和思想来解决这些问题。笔者以对话形式引入所介绍的主题概念,行文诙谐幽默却又鞭辟入里,力求帮助读者理解操作系统中虚拟化、并发和持久性的原理。

《操作系统导论》具有以下特色:

主题突出,紧紧围绕操作系统的三大主题元素——虚拟化、并发和持久性。

以对话的方式引入背景,提出问题,进而阐释原理,启发动手实践。

包含众多“补充”和“提示”,拓展读者知识面,增加趣味性。

使用真实代码而不是伪代码,让读者更加深入透彻地了解操作系统。