谨以此文献给UNIX50周年。作者孟宁,转载请注明出处读行学堂。
“三岁看大,七岁看老”的说法在心理学上得到一定程度的印证,也就是说早年的教育、环境和经历对一个人的成长起到非常重要的作用,因为能有效促进大脑的发育。所以杰出的人物成功的原因大多可以追溯到童年。同样的道理,为了深入理解操作系统,我们不仅需要学习操作系统原理,还需要从操作系统成长的过程说起。
最初并没有操作系统。在IBM 701开放式计算站(open shop)上是由它的使用者手动操作的,工作效率自然十分低下,为了有效利用IBM 701,每个用户被分配了一个最低15分钟的计算时间。在这15分钟里,使用者通常要为配置设备而花掉10分钟,等准备工作完成的时候,他经常最多有5分钟的时间来完成实际的计算工作,大约浪费了2/3的时间。每个月因浪费的计算时间造成的花费高达14.6万美元。要知道那时可是1954年!
为了减少计算时间的浪费并使开发人员从电脑机房中解放出来,开发人员被要求在穿孔卡上准备程序和数据,然后提交到计算中心去执行。开放式计算站(open shop)由此变成了封闭的计算站(closed shop)。亚当.斯密在《国富论》中进行深入分析论证能有效提高生产效率的劳动分工在这里得到了应用。最初的操作系统可以被认为是封闭的计算站(closed shop)里的操作员。
最早期的操作系统软件只是一些API函数库,并且大多重要的工作还是由操作员来完成。开发人员需要编写程序在计算机上运行,发现每个开发人员和编写每个程序都需要处理一些共同的东西,比如I/O处理的底层代码,自然就总结出一些常用的库函数便于开发人员直接调用,这些API函数大概就算是最初的操作系统的源头吧。如果最初操作系统只是一些API函数的话,那操作系统最核心的功能任务管理当时是怎么做的呢?
图:IBM 7094工作流程示意图
通常在这些大型机上由操作员来控制一次运行一个程序。以IBM 7094的工作流程为例,操作员从开发人员那里收集一组组穿孔卡片,然后使用卫星计算机把卡片上的作业输入到磁带上,然后这个磁带被安装到一个与主计算机相连接的磁带机上,这便是输入Input。主计算机按照程序在磁带中出现的顺序,每次运行一个,并将数据输出到另一个磁带上。最终,输出数据的磁带被移动到卫星计算机中,并通过行式打印机打印出来,这便是输出Output。
当主计算机执行程序的时候,两台卫星计算机同时做着输入和输出的工作。操作员完成了现代操作系统需要做的主要工作,比如程序运行的顺序。如果你想让你的程序得到优先执行,你得通过操作员想办法插队。
这种计算模式就是批处理(Batch Processing)系统,IBM 709所使用的共享操作系统(SHARE operating system)是早期的批处理系统。批处理系统一般先做好准备工作,然后由操作员以分批的方式来执行程序。这时的计算机还没有以交互方式使用,因为早期的计算机非常昂贵要有效利用计算机的机时,不能让计算机闲着。
系统调用(System Call)概念的诞生是操作系统发展的一个重要里程碑。Atlas Supervisor是第一个提出现代操作系统诸多概念的系统,它率先采用了系统调用的工作机制。
系统调用和API函数过程调用(Procedure Call)有何不同呢?系统调用的采用将程序的执行权限进行了划分,就像Linux系统分为用户态和内核态,系统调用将用户程序和操作系统之间进行了隔离,通过添加一些特殊的硬件指令和硬件状态让用户程序进入操作系统的过程更加正式、可控,这样有效保护操作系统提供的底层代码,使得整个系统更加稳定,不会让用户程序的错误造成整个系统的崩溃。普通的API函数过程调用没有得到任何保护,系统调用机制的采用使得操作系统超越了早期操作系统只是提供一些底层API函数库的状况,这时的操作系统超越了API库函数,因为通过系统调用提供了有效的保护机制。
系统调用和函数过程调用之间的关键区别:系统调用将控制跳转到操作系统中,同时提高硬件特权级别(进入内核态),用户程序在用户态运行,这意味着硬件限制了用户程序的功能。在用户态运行的用户程序通常不能直接发起I/O请求,不能直接访问任何物理内存或向网络上发送数据包。用户程序只能通过系统调用来访问底层硬件提供的功能,通常通过一个称为陷阱(trap)的特殊指令,比如x86指令集中的int 0x80,硬件将控制权跳转到预先指定的陷阱处理程序(即系统调用处理入口),同时将特权级别提升到内核态,在内核态操作系统可以完全访问系统硬件。当操作系统完成系统调用请求的服务时会通过特殊的陷阱返回指令(比如x86指令集中的iret)将控制权交还给用户程序,返回到用户态,回到用户程序离开的地方继续执行。
多道程序(Multiprogramming)从根本上改变了操作系统。在大型机时代之后,进入小型机(minicomputer)的时代,像数字设备公司DEC的PDP系列就是小型机的经典,这时计算机的成本更低更加实惠,同时硬件功能也日趋强大。这些变化同时也使得处理器开始能够支持程序的并发执行和控制。中断能够使得一个处理器控制多道程序的并发执行,这就变成了多道程序编程。
多道程序操作系统不是一次只运行一个程序,而是将大量程序加载到内存中并在它们之间快速切换,从而提高了CPU的利用率。这种切换是非常重要的,因为I/O访问速度很慢,在I/O访问过程中CPU空闲,因为CPU在等待输入数据或者等待输出完成,输入和输出虽然都在计算机内部,但是和前文所述IBM 7094的卫星计算机1401所做的工作并没有本质的区别。CPU空闲的时候为什么不切换执行其他用户程序呢?通过快速切换不同的用户程序,CPU的利用率可以得到大大提高。
小型机时代最成功的操作系统当属UNIX操作系统,UNIX汇集众多操作系统的思想,尤其是继承了Multics系统的诸多思想,贝尔实验室的Dennis Ritchie和Ken Thompson创造了简单而强大的UNIX操作系统。
至此操作系统的内在成长发育告一段落,它从无到有,从弱到强,直到UNIX操作系统诞生并统治小型机时代。操作系统从幼年到成年的过程除了经历了硬件环境的不断升级,还经历诸多新思想、新方法的洗礼,日趋成熟、稳定和强大。
和每一个年轻人的初入社会的经历一样,有人试图利用你控制你,有人面对你的青春活力感受到了威胁拒绝你排斥你,当然更多的人对你很无知冷漠应对。成年以后的操作系统也一样经历了一些波折。一方面UNIX相关的厂商试图控制对UNIX的所有权维护公司的利润,限制了UNIX的发展;另一方面操作系统在个人计算机兴起的初期出现了一次大的倒退。
图:Dennis Ritchie和Ken Thompson在贝尔实验室
笼罩在UNIX上的阴影。在操作系统的历史上,UNIX的地位举足轻重。1969年,Dennis Ritchie和Ken Thompson在贝尔实验室开始尝试寻找Multics的替代品。1971年底,他们开发的UNIX系统能够在PDP-11小型机上支持3位用户。然而,直到1973年UNIX内核用C语言重写之后人们才开始知道它的存在。在1974年之前根本没有出版过关于UNIX的任何相关文献。随着计算机的小型化,小型机(尤其是PDP-11)催生了一批新用户,他们对现存的操作系统软件感到失望,这群人更倾向于UNIX系统。UNIX操作系统提供的功能都不是全新的东西,而是使已经有的操作系统的功能使用起来更简便。UNIX系统对于开发人员很友好,提供了C语言编译器,开发人员很容易编写自己的程序并分享源代码,这使得UNIX非常受欢迎。UNIX成为开放源代码软件的早期形式,很重要的原因是作者向所有请求的人免费提供源代码。源代码的可读性也非常重要,UNIX是用C编写的内核比较容易理解,以致吸引其他人为UNIX添加新的、很酷的功能。到了十九世纪八十年代中期,UNIX已经成为了操作系统中领先的、事实上的行业标准,并诞生了诸多UNIX版本,比如由加州大学伯克利分校团队发布的BSD版本非常棒,还有Sun公司的Solaris、IBM公司的AIX、HP公司的HPUX等。随着UNIX带来的市场蛋糕越来越大,AT&T及贝尔实验室与这些不同的UNIX厂商产生了有关UNIX版权的法律纠纷,导致UNIX的传播速度有所放缓,这是律师参与其中的不幸结果,因为很多人怀疑UNIX能否存活下去。
早期个人计算机在操作系统上的大倒退。UNIX上笼罩阴影的同时一种称为个人计算机PC(Personal Computer)的机器,相对于小型机价格便宜性能不错,非常适合大众。在苹果公司的Apple II和IBM PC的引领下,很快这种可以放到桌面上的个人计算机占领了主流市场。由于早期的PC操作系统开发人员忘记了或许从未知道小型机时代的经验教训,以致在PC操作系统上出现了诸多痛苦的经历。早期的PC操作系统,比如微软的DOS并不认为内存保护很重要,造成恶意或非恶意的用户程序能够完全访问整个内存;第一代macOS的进程调度策略造成意外陷入无限循环占用整个系统导致重新启动。
图:Steve Jobs
PC操作系统经历过一段时间的痛苦历程后很快就重新站在了前辈操作系统打下的地基上。微软的Windows操作系统采用了操作系统历史上所有伟大的思想,特别是从Windows NT开始微软在操作系统技术上有了一个巨大的飞跃。乔布斯重新回到苹果公司时带着基于UNIX的NeXTStep操作系统,并以此为基础打造了macOS X,使得UNIX在台式机和笔记本上非常流行。对于小型机UNIX用户来说,1991年芬兰年轻的大学生Linus Torwalds编写了一个UNIX的克隆版本Linux,完全拷贝了UNIX系统背后的原则和思想,但没有使用UNIX的源代码,从而避开UNIX的版权法律纠纷,同时Linux的诞生也开启了现代开源软件运动。
图:Linus Torvalds
互联网时代手机操作系统没有走弯路直接站在了UNIX之上。手机操作系统被谷歌公司的Android操作系统和苹果公司的iOS操作系统垄断了市场。Android是基于Linux内核的手机操作系统,而Linux是UNIX的克隆版本;iOS操作系统的源头更是可以直接追溯到UNIX系统。至此操作系统发展到了人生的巅峰。
“花未全开月未圆,便是人生好时节”,操作系统似乎也逃不出物极必反的魔咒,伴随着万物互联、车联网、5G等新应用新技术的出现,操作系统似乎开始进入“中年危机”,操作系统等待着您即将给它注入的新的生命活力。
参考文献
[1]Per Brinch Hansen "The evolution of operating systems." In Classic operating systems, pp. 1-34. Springer New York, 2001. 翻译:http://219.219.220.231/wiki/OSEvolution