1 介绍
一台现代计算机包含:处理器、主存、磁盘、打印机、键盘、鼠标、显示器、网络接口和输入输出设备。这一切看起来很平常,但其实是一个很复杂的硬件架构。作为一个程序员,如果要使用一台计算机,不可能每个模块的细节都搞清楚,也不可能自己去管理所有的设备组件。出于这个原因,计算机一般会预装操作系统,操作系统的任务就是:1.提供一个更好、更简单、更干净的计算机模型;2.管理所有的设备资源。
很多读者可能用过一些操作系统,比如Windows、Linux、FreeBSD、OS X。用户一般通过接口程序和操作系统打交道,用户接口程序主要有两种:1.基于命令行的shell;2.基于图形界面的GUI。虽然用户通过shell或GUI和操作系统交互,但是这两者并不是操作系统的一部分。
图1-1是计算机主要组件的层级图。硬件位于最底层,主要包括:芯片、主板、磁盘、键盘、鼠标、显示器等。硬件之上是软件层。大多数操作系统有两种操作模式:内核模式和用户模式。内核模式又叫做内核态、管理员模式、管态,用户模式又叫做用户态、目态。操作系统运行在内核模式下,可以访问所有的硬件资源、执行所有的机器指令。其他的任何软件都运行在用户模式下,只能访问一部分机器指令,没有权限执行机器控制和IO相关的指令。
用户接口程序是用户模式下的最底层软件,用户就是通过它启动其他应用程序的,比如浏览器、电子邮箱、音乐播放器。这些应用程序在运行时,会大量使用操作系统提供的接口。
操作系统运行在硬件之上,为上层的所有软件提供基础。操作系统和其他上层软件的一个重要区别在于:用户可以随意的安装、卸载甚至自己开发一款软件,但是却不可以自由地写自己的时钟中断处理程序,因为这是操作系统的一部分,硬件会保护操作系统防止用户篡改。但这个区别也不是绝对的,比如一些嵌入式系统就没有内核模式,一些基于JAVA的解释型系统使用解释器(而非硬件)分离组件。
另外,在很多系统里面有这样一类程序,它们运行在用户模式,却帮助操作系统执行一些特权功能。比如用户密码修改程序,它不属于操作系统,并不在内核模式运行,但是它执行的功能是敏感的,需要通过特殊手段来保护的。在一些系统里面,这种现象更加极端,比如文件系统在传统意义上被认为是操作系统,却运行在用户模式。在这些系统里面,边界变得不再清晰。运行在内核模式下程序必然是属于操作系统的,但是运行在用户模式的程序也可能属于操作系统。
操作系统和其他应用程序除了所处的层级不同,还存在很多方面的差异。尤其是操作系统的庞大、复杂、历史悠久等特点。像Linux或Windows,它们的核心源代码是五百万行代码的量级,甚至更多。想想这是什么概念:如果把这些代码打印成书籍,每页50行,每本书1000页,就能打印100本书,足足填满一个书架。想象一下如果你找了一份维护操作系统的工作,上班的第一天你的老板指着一个书架对你说:“年轻人好好干!“,你会不会疯掉?更恐怖的是,这只是运行在内核模式的那部分代码。如果把基础的共享库加进来,Windows的代码将达到七千万,相当于10到20个书架。(这还不包括一些基本的软件,比如IE浏览器、媒体播放器等)
现在你应该能明白为什么操作系统历史悠久了吧,因为要开发一款操作系统实在太难了,一旦你成功开发一款操作系统,你是不会轻易抛弃它的。即使存在缺陷,你也会选择不断的打补丁、优化、重构,也不会轻易的推翻一切,重新开发一款操作系统。操作系统总是在不断的衍变,Windows 95/98/Me基本上是一款操作系统,Windows NT/2000/XP/Vista/Windows7是另一款操作系统。
除了Windows系统,UNIX系统也经历了多年的衍变。衍生出很多版本:System V、Solaris、FreeBSD。这里需要注意的是一款类UNIX系统Linux,虽然Linux在模块划分上和UNIX非常相近,也和UNIX系统高度兼容,但是Linux系统使用的是一个全新的代码库。
1.1 操作系统是什么
要给操作系统下个定义,很难!我们只能说操作系统是一款运行在内核模式的软件,即使这么说,依然是不准确的,因为有些操作系统没有内核模式。但是可以确定的是,操作系统执行着两块功能:1.为应用开发者和应用程序提供一系列干净的资源抽象而非混乱的硬件资源;2.管理硬件资源。
1.1.1 对资源进行抽象
机器语言级别的大多数计算机架构这样的:指令集、内存组织、IO、总线结构。这种架构对于编程来说是非常原始和笨拙的。就拿SATA硬盘来说,如果程序员要开发程序对硬盘进行读写操作,那么他就需要知道硬盘提供的底层指令,从而去操纵读写头进行寻道、读写扇区等。这样的接口文档有几百上千页的内容。显然,任何一个明智的程序员都不会在硬件层面上对磁盘进行编程。取而代之的是磁盘驱动程序,它会负责和硬件打交道,并为上层应用提供读写接口。操作系统就包含许多的驱动程序用于控制IO设备。
即便驱动程序提供了较为简单的接口,但这种接口对于上层应用来说依然很低级、很笨重。为了进一步简化,所有的操作系统在驱动程序的基础之上,为磁盘提供另一层抽象:文件。有了这一层抽象,上层的应用程序就能够方便地对文件进行创建、读取和写入了,根本不用关心底层的硬件是如何工作的。
这种抽象的理念就是解决所有复杂性问题的关键。往往好的抽象设计能够将几乎不可能解决的任务分解成两个可解决的任务:1.定义抽象模型并进行实现;2.使用抽象解决问题。操作系统的工作就是创建抽象、实现抽象、管理抽象出来的对象。所以想要理解操作系统,抽象是关键。
硬件层面的处理器、内存、磁盘和其他设备都非常的复杂、差异大、笨重。如果要使用它们,都需要开发相应的软件。造成这些现象的原因,有时候是因为要对老的硬件向后兼容,有时候是为了省钱。但是硬件设计师往往不会考虑这些问题。所以操作系统的一个主要任务就是屏蔽硬件的差异性和复杂性,为上层应用呈现出漂亮的、干净的、优雅的、一致的抽象。
这里我们需要明确的是,操作系统的实际用户是上层的应用程序。应用程序直接和操作系统及其提供的抽象打交道。相对而言,终端用户和用户接口提供的抽象打交道。这里,终端用户就是计算机的使用者,用户接口就是上文提及的shell和GUI。
1.1.2 对资源进行管理
对于计算机组件层级:从上往下看,操作系统主要为上层应用提供抽象;从下往上看,操作系统负责管理底层硬件资源。现代计算机由处理器、存储器、定时器、磁盘、鼠标、网络接口、打印机以及各种其他设备组成。从下往上的角度看,操作系统有序地分配硬件资源给上层应用使用。
现代操作系统允许多个程序载入内存并同时运行。想象一下,如果一台计算机上同时运行着三个程序,这三个程序同时使用同一台打印机进行打印,会发生什么结果?结果有可能,一张纸上,一段内容是第一个程序的,一段内容是第二个程序,一段内容是第三个程序的。三个程序的内容混乱、无序地打印到纸上。操作系统为了解决这一问题,会把每个程序要打印的内容分别缓存到磁盘上,当某个程序结束运行时,操作系统就把该程序在磁盘上缓存的内容发送给打印机进行打印。
当多个用户使用一台计算机(或网络)时,就更需要管理并保护内存、IO设备和其他资源,因为用户之间可能会相互干扰。另外,用户通常不仅需要共享硬件资源,还需要共享信息资源(如文件,数据库等)。从这个角度看,操作系统的主要任务是授权资源请求、跟踪资源使用情况、协调资源请求的冲突。
资源管理包括两种方式的复用资源:时间复用和空间复用。对于时间复用型资源,多个程序或用户是轮流使用的。比如,一个CPU运行着多个程序,操作系统首先分配CPU给一个程序使用,当这个程序运行一段时间后,操作系统会把CPU分配给另外一个程序,以此类推,最终经过一轮循环使用后,CPU又会分配到第一个程序。至于哪个程序先使用资源,哪个程序后使用资源,每个程序应该使用资源多长时间,这个是由操作系统决定的。另外一个时间复用的例子是共享一台打印机。当多个打印任务在排队的时候,操作系统就需要决定打印的先后顺序。
另一种资源复用方式是空间复用。与时间复用方式不同,程序并不是轮流使用资源,而是资源被分解成多个部分,每个程序使用一部分。比如,一块内存被多个程序同时使用,每个程序被载入到不同的内存区域。假设计算机上有足够的内存去存放多个程序,那么将多个程序同时放入内存运行效率更高。当然这样一来就会有新的问题:公平性问题、资源保护问题。这些都是需要操作系统去解决的。另外一个空间复用的例子是磁盘。很多系统里面一块磁盘同时存放着多个用户的文件。操作系统负责着磁盘空间的分配和跟踪。
1.2 操作系统历史
操作系统经历了多年的发展,在它的发展历程中,始终和计算机的架构紧密关联。下面我们简要的介绍下最初的几代计算机,看看它们采用的操作系统。
第一台真正的数字计算机是由英国数学家Charles Babbage(1792–1871)设计的。Babbage花费了大部分的时间和财力去试图构建他自己的“分析引擎”,但最终没有正常运行起来。因为它是纯粹的机械设计,而那个时代的技术有限,没法提供高精度的轮子和齿轮。自不必说,他的分析引擎并没有操作系统。
顺便说一段有趣的历史,Babbage在设计他的分析引擎过程中,他意识到需要相关的配套软件,所以他雇佣了一个年轻的女性Ada Lovelace(英国著名诗人拜伦伯爵的女儿)。她就是世界上第一个程序员,编程语言Ada就是以她的名字命名的。
1.2.1 第一代(1945-55):真空管
在Babbage失败的努力之后,直到第二次世界大战期间,数字计算机的建设才取得了一些进展,推动了战争的爆发。John Atanasoff教授和他的研究生Clifford Berry在爱荷华州立大学构建了第一台功能齐全的数字计算机。这台计算机使用了300个真空管。大约在同一时间,柏林的Konrad Zuse用机电继电器建造了Z3计算机。1944年,一群科学家(包括Alan Turing)在英格兰的布莱切利园建造并编程了巨人计算机,Howard Aiken在哈佛建造了Mark I计算机,William Mauchley和他的研究生J. Presper Eckert在宾夕法尼亚大学建造了ENIAC计算机。这些计算机各式各样,有的是二进制的,有的使用了真空管,有的是可编程的。但它们的共同点是都很原始,即使进行一个最简单的计算也要耗时几秒钟。
在早期的日子里,专门有一组人全权负责设计、构建、编程、操作、维护每一台机器。所有的程序都使用机器语言编写,甚至更糟的是,通过连接数千根电缆到插头板来完成布线,以控制机器的基本功能。那个年代没有编程语言的概念,甚至连汇编语言都还没出现,更别提操作系统了。以前的程序员都是这么操作计算机的:在墙上的注册表报名,然后进入机房,把线路连接板插入计算机,接下来就是几个小时漫长的等待,心里还得祈祷计算机运行的过程中真空管不要烧掉。那个时候的计算机只能解决一些简单的数学和数值问题,比如正弦、余弦、对数或大炮轨迹等。
到了1950年代初期,随着穿孔卡片的引入,程序有所改进。程序可以在卡片上编写和读取,而不再使用线路连接板。
1.2.2 第二代(1955-65):晶体管和批处理系统
1950年代中期,晶体管的引入从根本上改变了计算机发展面貌。计算机已经变得足够可靠,开始批量生产并售卖给付费用户,帮助用户做一些有用的工作。设计师、构建师、操作员、程序员和维护人员也不再是同一拨人,他们开始按角色划分了。
这些机器被称之为大型机,通常被锁在庞大的、带空调的机房里,有专业的操作人员去运行。当时的大型机价格很昂贵,一般数百万美元,只有大型企业、主要政府机构或大学才能买得起。为了执行一个任务(程序),程序员首先需要使用FORTRAN或汇编语言把程序写在纸上,并打到卡片上。然后带着一叠卡片去输入室把卡片交给操作员,接下来就可以去喝杯咖啡,静静地等待结果了。
当计算机完成任务后,结果会输出到打印机,操作员会撕下打印出来的纸张拿到输出室交给程序员。如果需要FORTRAN编译器的话,那么操作员需要从文件柜里面拿到编译器程序并读入计算机。为了执行一个任务,大部分的时间都被浪费在操作员从一个操作室走到另一个操作室。
考虑到一台计算机的成本太高,如果每运行一个任务都要浪费这么多时间话,那太不值了。所以人们想到了一个解决方案:批处理系统。每次收集多个任务带到输入室,有一台相对便宜的、专门用于读取卡片、拷贝磁带、打印输出的计算机(如IBM 1401),会把多个任务读到磁带里。而昂贵的大型机(如IBM 7094)负责任务的执行。
在大约花一个小时收集一批任务之后,卡片上的内容被读取到磁带上,磁带被运到机房,安装到磁带驱动器上。这个时候操作员就会启动一个特殊的程序执行磁带里面的内容,这个程序就是操作系统的雏形。这个程序按顺序执行磁带里面的每个程序,并且把每个程序的运行结果输出到另一个磁带。当这一批任务都执行完成之后,操作员就拔出输入磁盘和输出磁盘,插入下一个批任务磁带,并把输出磁带带到1401,把结果打印出来。
一个典型的任务(程序)结构如图所示:第一张
第二代的大型机主要用于科学和工程计算,比如求解物理和工程领域中的偏微分方程。基本上使用FORTRAN和汇编语言编程。典型的操作系统有FMS、IBSYS、IBM的7094操作系统。
1.2.3 第三代(1965-80):集成电路和多道程序设计
1960年代早期,大部分计算机制造商有着两条截然不同的、相互不兼容的产品线:1.面向字的、大规模的科学计算机,比如IBM的7094,专门用于科学和工程领域中的工业强度数值计算;2.面向字符的商业计算机,比如IBM的1401,广泛用于银行和保险公司。
开发和维护两个完全不同的产品线对于制造商来说代价过于昂贵。此外,许多用户最初只需要一台小型计算机,但后来随着业务的发展壮大,为了获取更快的运行速度,就需要一台大型计算机来运行他们之前的所有程序。
IBM为了解决这两个问题,开发了System/360。360是一系列软件兼容的计算机,能够兼容1401到7049,并且比7049功能更强大。这个系列的机器只在价格和性能上存在差异(内存大小、CPU速度、IO设备数量等)。它们的架构和指令集都是一样的,所以一台计算机上编写的程序完全可以在这个系列的其他机器上运行。自此,360就被用于科学和商业计算,满足了所有用户的需求。在接下来的岁月里,IBM推出了很多向后兼容的新的产品系列,使用了更加现代化技术,比如370,4300,3080和3090。Z系列是最近的一个系列,已经和原来的系列有了较大的差异。
IBM的360系列是第一个使用了(小规模的)集成电路的主要计算机产品。相较于第二代的基于晶体管的计算机,有了较大的价格和性能优势。IBM取得了成功之后,其他主流制造商也采用了相同的模式,制造一系列相互兼容的计算机。这些系列的计算机一直发展到今天,很多计算机中心用来管理大型数据库(比如航空订票系统),或者用于大并发量的万维网服务。
凡事都是有利有弊的,IBM初衷是美好的,把两条产品线合并成一条产品线,使得所有的软件包括操作系统(OS/360)在所有的机型上都兼容。但实际上要完完全全做到这一点是不可能的,各种机型的差异太大了,有的小型系统(类似1401系列)只需要把卡片上的程序读进磁带,有的大型系统(类似7094系列)则需要完成大型计算;有的系统外设多,有的系统外设少;有的系统运行在商业环境,有的系统运行在科学领域。
为了解决各种冲突、兼容性问题,操作系统变得越来越庞大,超过FMS两到三个数量级。由几千个程序员编写的数百万行汇编代码组成,当然随之而来的也有数以千计的BUG,所以不断有新的版本迭代去修复问题。为了解决旧的问题,往往又会引入新的问题,操作系统越来越庞大、越复杂,所以一直有很多BUG。
虽然OS/360系统和其他制造商生产的操作系统规模庞大、问题繁多,但是它们满足了大部分用户的需求。并且实现了多道程序设计技术,以往的7094计算机,在等待磁带插入或者IO操作的期间,运行的任务会暂停,CPU是完全闲置的。对于CPU密集型的科学计算来说,IO操作不频繁,这点浪费不算什么。但是对于商业数据处理,等待IO的时间通常可达总时间的80%-90%,所以必须采取有效的措施避免CPU过度闲置。
如图所示,解决方案就是把内存划分为多个分区,每个任务载入不同的分区。当某个任务等待IO操作的时候,另外一个任务就可以使用CPU。理论上,如果内存里面一次性载入的任务足够多,那么CPU将会保持几乎100%满负荷工作。但是内存里面存在多个任务的话,就需要特殊的硬件对其保护,以防止它们产生冲突、相互干扰。当时的360和其他第三代操作系统专门配备了这样的硬件。
第三代操作系统另一大突破是使用了磁盘取代了磁带,当某个程序执行完成之后,操作系统就从磁盘上加载一个新的程序到空白内存分区去运行。这种技术被称为假脱机(spooling : Simultaneous Peripheral Operation On Line),对于输出也是同样到的道理,某个程序执行的结果输出到磁盘。有了假脱机后,1401系列就不在需要了,很多磁带也消失在大众视野之外。
虽然第三代操作系统适用于大型科学计算和大量的商业数据处理,但它们本质上还是基本的批处理系统。很多程序员还是很怀念第一代系统的日子,因为那个年代,程序员管理着程序的运行,他们能够很快的对程序进行Debug。但是第三代系统就不同了,程序员只能够把程序交给操作员,然后静静的等待结果。等待结果往往需要几个小时,如果等了半天被告知编译出错,因为少写了一个逗号,程序员就要崩溃了,这样的方式太浪费时间了。
分时系统的出现解决了这一问题,这种系统实际上是多道程序设计的升级版,每个用户通过一个在线终端使用同一台计算机。在一个分时系统里面,假如登录了20个用户,其中17个人在思考问题、聊天亦或是喝咖啡,所以实际上可能只有3个人需要使用CPU跑程序。由于人们一般都用一些短命令对程序进行Debug,分时系统为用户提供了一种快速的、交互式的服务或者当CPU闲置的时候在后台跑大型批处理任务。第一个分时系统(CTSS:Compatible Time Sharing System)是由麻省理工大学在IBM7094的基础上修改而成的。可是分时这个概念在当时并没有普及,直到相应的硬件保护装置的出现。
继CTSS系统成功之后,麻省理工贝尔实验室和通用电气公司决定着手开发一款“实用计算机”,这款计算机可以同时支持数百个分时用户。这款计算机的模型参考了电力系统,电力系统模型是这样的:如果你需要用电的时候,只需要把电器插到墙上的插座,就可以用电了。这款计算机系统叫做多路信息计算系统(MULTICS : MULTiplexed Information and Computing Service),它的设想是通过一台中央巨型计算机,为整个波士顿地区的人提供计算服务,这个系统的运转速度比GE-645大型机快一万倍,四十年后就能卖出去数百万台,单价不到一千美元。这个想法简直就是科幻小说。
MULTICS只是取得了一点成功。它是由一台计算机同时为数百个用户服务,相较因特尔386的PC机,虽然多了些IO性能,但整体性能并没有高出太多。MULTICS最终没有在世界范围内流行起来,原因有很多,其中最重要的一点是它是用PL/I语言编写的,而PL/I编译器是几年后才开发出来的,那个时候已经为时已晚了。
长话短说,MULTICS将很多开创性的思想引入了计算机文明,但是要把这些思想实现成具体的产品以取得重大商业成就太难了。贝尔实验室退出了这个项目,通用电气公司完全退出了计算机业务。然而,麻省理工大学最终坚持了下来,实现了MULTICS产品。这款产品由收购了通用电气公司的霍尼韦尔公司出售,全球约有80家大公司和大学购买并安装了。
二十世纪末,实用计算机的概念彻底破灭,但这个概念可能会以云计算的形式再度出现,各个终端机远程连接到巨型计算机中心。计算机中心负责计算,而终端机只负责处理用户界面。这里的动机是,大多数人不想管理一个日益复杂和繁琐的计算机系统,而宁愿由一组专业人员来做这项工作,例如,为数据中心的公司工作的人。电子商务已经朝着这个方向发展,各种各样的公司在多处理器服务器上运行电子邮件服务,客户机连接这些电子邮件服务器,这非常符合MULTICS设计的精髓。
尽管MULTICS在商业上并没有取得成功,但它对后续操作系统产生了巨大的影响,尤其是UNIX及其衍生系统FreeBSD、Linux、IOS和Android。如果读者有兴趣去了解MULTICS系统的相关信息,可以去官方网站查询:www.multicians.org。
第三代计算机历史的另一个重大突破就是微型机的惊人的增长速度。如一开始的DEC PDP-1,虽然只有4K存储,但售价却高达12万美元,但是依然非常的热销。对于某些非数值工作,它的处理速度几乎和7094一样快,为计算机领域产生了一个全新的产业。
贝尔实验的一位曾经参与研发MULTICS项目的科学家,Ken Thompson,后来发现了一个无人使用的小型PD-7小型计算机,他就着手编写一个精简的、一个用户版本的MULTICS。这个系统后来就发展成了UNIX,一个在学术界、政府机构和许多公司中都备受欢迎的系统。
我们会在第10章详细介绍UNIX系统,这里只做简要介绍。由于UNIX的源代码是开源的,所以其他组织都可以基于UNIX做二次开发,实现各自的操作系统。当时的两个主要版本是:AT&T开发的System V和伯克利大学开发的BSD,它们又有各自的小版本。为了能够编写可以在任何UNIX系统上运行的程序,IEEE为UNIX开发了一个标准,称为POSIX,现在大多数UNIX版本都支持这个标准。POSIX定义了UNIX系统必须支持的最小系统调用接口集。事实上,其他一些操作系统现在也支持POSIX接口。
顺便说个故事,1987年的时候,出于教育的目的,作者发布了一款小型的UNIX克隆版,名叫MINIX。从功能上看,MINIX和UNIX非常的接近,也支持POSIX。当MINIX经历了版本迭代,演变到MINIX3的时候,已经达到了高度模块化和高可靠性。它能够在运行的时候检测并替换掉故障模块,都不需要重启,所以对运行中的程序没有干扰。MINIX一直致力于高可靠性和高可用性。有一本书专门介绍介绍它的内部运作原理并列出了源代码。读者也可以去官方网站查阅资料:www.minix3.org。
MINIX虽好,但不是免费版。芬兰学生Linus Torvalds就想实现一款免费版的,所以他着手开发Linux。这款系统是基于MINIX开发的,最初的版本支持了各种MINIX特性,如文件系统。Linux后续的版本,被许多人参与进来一起开发,进行了大量的扩展,但仍然保留了MINIX通用的底层结构。
1.2.4 第四代(1980-今):个人计算机
随着大规模集成电路的发展,一块芯片能够在一平方厘米硅片上集成数千个晶体管的,这就促使了个人计算机时代的到来。就架构而言,个人电脑(最初称为微型计算机)与PDP-11小型计算机并没有大的差别。除了价格差别较大。小型计算机主要用于公司、大学;微处理器芯片使单个人拥有自己的个人计算机成为了可能。
1974年,因特尔推出了第一款8位的CPU(8080),当时就需要为它配备一款操作系统。因此因特尔邀请了一位顾问(Gary Kildall)去开发一款操作系统。Gary Kildall和他的一个朋友一开始为新发布的8英寸软盘开发了一款控制器,然后把软盘挂载到8080处理器上,这样就诞生了第一台微型计算机。Kildall随后又为它编写了一个基于磁盘的操作系统(CP/M : Control Program for Microcomputers),并且向因特尔公司索要版权。当时因特尔并不觉得微型机有前途,所以就把版权给了他。Kildall随后就成立了一家公司(数字研究公司),并进一步的开发CP/M,用于出售。
1977年,数字研究公司重写了CP/M,以使得其可以适用于8080、Z80和其他CPU芯片。许多应用程序都是在CP/M上运行的,使得它统治了微型计算机领域长达5年。
1980年代早期,IBM公司设计了自己的个人计算机(IBM PC),并寻求能够在它上面运行的软件。IBM的人就联系了比尔盖茨授权他的BASIC解释器。他们也咨询了比尔盖茨有没有一款能够运行在PC机上的操作系统。比尔盖茨建议他们联系数字研究公司,当时的操作系统领头羊。但是Kildall犯了一个重大的商业决策错误,他拒绝和IBM会面。更糟糕的是,他的律师也拒绝和IBM签署相关协议。最终,IBM只得回头去找盖茨,寻求一款操作系统。
当IBM回来找盖茨的时候,盖茨才想起来,有一家本地的计算机制造商(西雅图电脑产品公司),它们的一款操作系统DOS(Disk Operating System),很适合IBM的需求。盖茨就联系了这家公司,以75000美元买下了DOS。紧接着盖茨把买下来的DOS和自己的BASIC打包卖给了IBM。在使用过程中,IBM向盖茨提了一些修改需求,所以盖茨就雇佣了曾经开发的DOS的Tim Paterson,进行了二次开发。并且把修改后的更名为MS-DOS(MicroSoft Disk Operating System),这款系统很快就占领了IBM PC机的市场。通过这件事,就能看出来比尔盖茨的决策是非常明智的,他把MS-DOS卖给计算机公司,和硬件捆绑销售。而不是Kildall那样,只是把CP/M直接销售给终端用户。当这一切发生之后,Kildall突然了,死因不明。
1983年,IBM的后继产品IBM PC/AT计算机面世的时候,MS-DOS已经牢牢占领的市场,而CP/M已经穷途末路。MS-DOS后来广泛用于80386和80486。虽然MS-DOS一开始的版本很简单,但是后续的版本增加了越来越多的高级特性,其中不少是借鉴了UNIX。(微软很了解UNIX,甚至早期还卖过一款XENIX微型计算机。)
不管是CP/M、MS-DOS,还是其他操作系统,用户都需要通过命令行与之交互。直到1960年代,斯坦福研究协会的Doug Engelbart发明了图形化用户界面,才改变了这一情况。当时的GUI有着完整的窗口,图标,菜单和鼠标。施乐帕克研究中心采用这一设计,并把它加入到生产的计算机中。
一天,苹果公司创始人(乔布斯)拜访了施乐帕克研究中心,看到了他们设计的GUI,立即就意识到它有着无限的潜力。而施乐帕克研究中心并没有这么觉得,他们只是当做一项研究。乔布斯紧接着就着手开发一款带GUI的苹果电脑(Lisa),但是因为其售价太过昂贵,所以没有取得商业上的成功。乔布斯的第二次尝试,苹果Macintosh,就取得了重大的成功。不仅仅因为比Lisa便宜许多,更是因为Macintosh更加用户友好,使得即使用户不懂计算机也能上手使用。Macintosh很快受到了大众的追捧,被广泛应用于平面设计、专业数码摄影和专业数字视频制作等领域中。1999年,苹果公司采用了一款由卡内基梅隆大学的Mach微内核衍生出来的内核,该内核最初的用意是用来取代BSD UNIX内核的。因此,Mac OS X是一个基于UNIX的操作系统,尽管它具有非常独特的接口。
由于受到了Macintosh的强烈影响,当微软决定开发下一版MS-DOS系统的时候,它开发了一个基于GUI的操作系统(Windows), 一开始Windows是运行于MS-DOS之上的。所以这么看的话,Windows更像一个用户接口,而非一个操作系统。大概持续了10年的时间,从1985-1995年,Windows仅仅是MS-DOS之上运行的图形环境。1995年,微软发布了一款独立的操作系统Windows95,它引入了许多操作系统的特性,底层的MS-DOS只是用于启动系统、兼容以前的基于MS-DOS开发的程序。之后又在这个系统的基础上做了稍微的修改,1998年时发布了Windows98。95和98里面包含了很多16位英特尔汇编代码。
微软的另外一款独立的操作系统是Windows NT(New Technology),这款操作系统在一定程度上和Windows 95兼容,但是它是全新开发的系统。它是完完全全的32位操作系统。Windows NT的首席设计师是大卫·卡特勒,他也是VAX VMS操作系统的设计者之一,所以在NT中的一些设计想法来自于VMS。正是由于这点,VMS的所有者DEC起诉了微软。微软花了一大笔钱摆平了这件事。微软希望NT以及后续的系统版本都把MS-DOS移除掉,做成更加优秀的操作系统。想法是美好的,但现实并非如此。到了NT5的时候,微软更换了命名方式,叫做Windows 2000。它是Windows 98和Windows NT 4.0的下一版。
由于Windows 2000存在一些缺陷,微软又为Windows 98出了一个版本Windows Me。2001年的时候,Windows 2000的升级版Windows XP面世。XP是一款发行长达6年的系统,几乎取代了之前的所有Windows系统。
随着版本的演变,继Windows 2000之后,微软把Windows系列拆分成了两条产品线:客户端和服务端。客户端产品线主要基于XP,服务端产品线主要包括Windows 2003和2008。不久后还出了第三条产品线,用于嵌入式系统的。所有这些Windows版本都是以服务包的形式演变的。
到了2007年的时候,微软发布了XP的下一个版本操作系统Vista。它配备了一个全新的图形界面,拥有更高的安全性,以及许多新的或升级过的用户程序。微软期望Vista能够完全取代XP,可以天不遂人愿。反而还招致了很多批评和负面报道,主要由于过高的系统要求、限制性许可条款和数字版权管理的支持,这些技术使得用户更难复制受保护的材料。
随着Windows 7的到来,事情得到了大大的改观。由于它消耗的资源少了许多,所以用户都决定跳过Vista直接使用它。虽然Windows 7并没有引入太多的特性,但是它相对较小并且相当稳定。在不到三周的时间里,Windows 7就收获了比Vista长达七个月更多的市场份额。2012年的时候,微软发布了Windows 8,一个全新的外观、面向触摸屏的操作系统。微软希望新的设计将成为主导操作系统,运用在更广泛的设备上:台式机、笔记本电脑、平板电脑、电话和家庭影院。但是到目前为止,与Windows 7相比,市场渗透速度较慢。
在个人计算机领域,另一款优秀的操作系统UNIX(及类UNIX系统)。UNIX在网络和企业服务领域是最优秀的,同时也常用于台式计算机、笔记本电脑、平板电脑和智能手机上。在基于x86的计算机上,Linux逐渐成为Windows的替代品,在学生和越来越多的企业用户之间越来越流行。
顺便说一下,在本书中,我们将使用x86这个术语来表示自1970年代8086CPU以来的基于同一个指令集家族架构的所有现代处理器。基于二十世纪七十年代8086开始的指令集体系架构的所有现代处理器。x86主要有两大制造商:AMD和因特尔。它们制造出来的处理器在底层还是有较大差异的:有32位和64位的、有单核和多核的、有深层次管线和浅层次管线的等等。然而,对于程序员来说,它们差别不大,都能够运行35年前的8086代码。对于重要的差别,我们会引用显示模型来说明——用x86-32和x86-64表示32位和64位机。
FreeBSD是一款流行的UNIX系统,从伯克利的BSD项目衍生出来的。所有的Macintosh计算机都运行在FreeBSD的更新版本上(OS X)。UNIX通过高性能的RISC芯片,成为工作站的标准系统。它的衍生系统也被广泛的应用到移动设备,如iOS和Android。
许多UNIX用户,尤其是经验老道的程序员,喜欢命令行甚于图形界面,所以几乎所有的UNIX系统都提供一个由MIT开发的窗口系统X Window System(也叫做 X11)。这个系统处理基本的窗口管理,允许用户通过鼠标创建、删除、移动、调整窗口。通常一个完整的GUI可在X11上运行,如Gnome或者KDE,使得UNIX看起来就像Macintosh和微软的Windows。