从概念上讲,计算机的结构是总线型的:布置一根总线将各种硬件设备挂在总线(Bus)上。
(1)所有的设备都有一个控制设备,外部设备通过控制器与CPU进行通信。
(2)所有的设备之间的通信也需要通过总线。
为了提高计算机的效率,人们又设计出了流水线结构:仿照工业流水装配线,将计算机的功能部件分为多个梯级,并将计算机的每条指令拆分为同样多个步骤,使每条指令在流水线上流动,到流水线最后一个梯级时指令执行完毕。
下图展示了5个梯级的流水线结构,流水线上的每个梯级都可以容纳一条指令并同时执行。
在流水线的基础之上,为了进一步提高效率,人们又发明了多流水线、超标量计算和超长指令字等多指令发射机制。
除了指令执行单元外,计算机中的另一个重要部件是指令的存放单元,被称为存储架构。存储架构包括了缓存、主存、磁盘、磁带等。下图展示了一个包括寄存器在内的5级存储介质构成的存储架构。
从寄存器到磁带,每一级存储媒介的访问延迟和容量均依次增大,而价格却依次降低。从图中可以看出,寄存器的访问速度最快,容量最小,但成本却最高;磁带的访问速度最慢,容量最大,但是成本却最低。通过合理搭配,可以形成一个性价比颇高的存储架构。
中断是计算机里面的一个最为重要的机制,它也是操作系统获得计算机控制权的根本保证。其基本原理是:设备在完成自己的任务后向CPU发出终端,CPU判断优先级,然后确定是否响应。如果响应,则执行中断服务程序,并在中断服务程序执行完后继续执行原来的程序。下图简单地描述了中断机制:
所谓抽象,就是在根本上存在但现实中不存在的东西。抽象来源于具体,但又超越具体。
操作系统提供的抽象来源于显示,就是具体的计算机硬件,如CPU、内存、I/O设备等等。但又超出这些现实,给人提供了强于现实的东西,使人和应用软件感觉到更多、更好的硬件存在。
抽象不只是操作系统提供给用户的一个存在,它也存在于操作系统内部。操作系统内部分为不同的功能模块,而不同功能块之间互相提供的也是抽象。想想在我们得实际开发中,是不是也遵循着这样类似的原则?针对抽象编程?面向接口编程?依赖于抽象而不依赖于具体?
残酷的现实:世界上的人并非都是平等的,有些人生来占有的资源就多,而有的人占有的资源就很少。当有些人来了,其他人就得让出资源。程序亦是如此。
操作系统作为计算机的管理者,享有着更多的方便或权限。为了区分不同的程序的不同权限,人们发明了内核态和用户态的概念。
内核态就是拥有资源多的状态(或访问资源多的状态),也称为特权态。而用户态则是非特权态,在用户态下访问的资源会受到限制。例如,要访问OS的内核数据结构,如进程表等,则需要在特权态下才能做到。如果只需要访问用户程序里的数据,则在用户态下就可以了。
内核态:访问资源多,但可靠性、安全性要求高,维护管理都比较复杂;
用户态:访问资源有限,但可靠性、安全性要求低,维护起来比较简单;
那么,一个程序到底应该运行在内核态还是用户态呢?这取决于其对资源和效率的需求;下图展示了Windows操作系统的内核态与用户态的界限,我们可以看到哪些需要在内核态下运行,哪些只在用户态下运行。
计算机对于内核态和用户态的识别是通过CPU的一个状态位来实现的,这个状态位是CPU状态字里面的一个字位。所谓的用户态、内核态实际是CPU的一种状态,而不是程序的状态。通过设置该状态字,可以使CPU处于内核态、用户态或者其他的子态(有的CPU有更多种子态)。
换句话说:一个程序运行时,CPU是什么态,这个程序就运行在什么态。
那么,知道了是怎么实现的,那又是如何对用户态的访问进行限制的呢?在对用户态下程序执行的每一条指令进行检查,这种检查又被称为地址翻译,即对程序发出的每一条指令都要经过这个地址翻译过程(你可以将其理解为我们在实际开发中所作的权限管理,对用户发出的每个操作请求首先都经过一个Filter进行过滤),通过对翻译的控制,就可以限制程序对资源的访问。
单一体结构是最早期的结构,这时整个OS是一个巨大的单一体,运行在内核态下,为用户提供服务,如下图所示。
但单一体结构各功能块之间关系复杂,修改困难,牵一发而动全身,且容易形成循环调用造成死锁,于是有了下面的层次关系。
将操作系统的功能分成不同的层次,低层次的功能为紧邻其上一个层次的功能提供服务,而高层次的功能又为更高一个层次的功能提供服务,如下图所示。
从单一体和层次化结构的图中可以看出,操作系统的所有功能都在内核态下运行。但是,从用户态转为内核态是有时间成本的,这样就会造成OS的效率低下。于是,人们将操作系统的核心中的核心才放在内核态运行,其他功能都迁移到用户态运行,于是就有了下面的微内核结构。
进程是OS中的核心概念,它指的是一个运动中的程序。一个程序一旦在计算机里运行起来,它就称为一个进程。进程与进程之间可以进行通信、同步、竞争,并在一定情况下可能形成死锁。
内存是另一个核心概念,它是进程的存放场所。OS要做的就是对内存进行管理,使得数据读写高效、安全、简单。
文件是操作系统提供的外部存储设备的抽象,它是程序和数据的最终存放地点。OS要做的就是让用户的数据存放变得容易、方便和可靠。
操作系统是一个系统程序,即为别的程序提供服务的程序。那么,操作系统的服务是通过什么方式提供的呢?答案就是:系统调用(System Call)。
所谓系统调用就是:操作系统提供的API,用户通过调用这些API即可获得操作系统的服务。(想想是不是跟我们现在所作的什么Web Service、WCF、WebAPI、开放API之类的一致?)例如,如果用户程序需要进行读磁盘的操作,在C程序代码中可以使用如下语句来操作:
result = read(fd, buffer, nbytes);
这个read函数是C语言提供的库函数,而这个库函数本身则是调用的操作系统的read系统调用。具体的系统调用过程不是我们讨论的重点,但我们还是可以通过下图来看看这个read系统调用的过程。
邹恒明,《操作系统之哲学原理》,机械工业出版社
作者:周旭龙
出处:http://edisonchou.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。