本篇开始,将介绍操作系统相关知识,这一部分的知识涵盖操作系统通识到具体的平台。和本系列前面所有文章一样,力求精简但有所突破。
1. 硬件使用回顾
如果已经阅读过前面的文章,那么应该对计算机硬件执行计算的概念有所了解,这里做一下简单回顾,也是作为操作系统必要性的基础。
计算机硬件主要可以分为如下四大部分:
- CPU,包括控制单元CU和执行单元EU,执行单元其实还是通过算术逻辑单元ALU来实现功能
- 存储器,包括内存、Cache,以及最贴近CPU的寄存器等
- 输入输出设备,包括键盘、鼠标、显示器、磁盘等等
- 总线,连接上述三种元器件的电气线缆,起到连通的作用
那么典型的计算过程是:
- 基于CPU支持的指令集ISA编写任务描述
- 通过输入设备输入到存储器中,注意这期间使用到了总线
- CPU执行计算任务,期间同样使用到了总线
- 通过输出设备输出结果,期间使用到了总线
看起来也没什么问题,程序员应该有能力独立完成上述步骤,顺利调用CPU进行计算。但有一个问题要先引起重视,那就是总线的使用时机。
1.1 总线使用
图中可以看出,总线分为地址总线、数据总线、控制总线三种,这里不去讨论分类的细节,毕竟从名称上所能观察到的含义足够使用。思考的问题是,为什么总线要分类?
总线之所以要分类,首先是因为总线总数有限,就是说从硬件层面,不能将每两个可能发生通信的组件之间全部用总线相连。既然不能形成点对点专线,而组件之间又确实有通信的需求,那就只能采取一个办法,共用总线。
共用总线是好事,毕竟远离CPU的线缆大部分时候都是处于空闲状态的,假如能够共享硬件总线,无论是从经济还是电路设计的角度来讲,都是一件节约成本的事。简单的共用无非就是大家约定俗成,分时段使用,不过这样一点也不高效,毕竟使不使用总线要看任务描述中的指令顺序,要看指令的操作对象是数据、地址还是需要控制。为了更加高效地利用线缆,那么一定需要一个类似总线控制的单元。该单元管理并维护着所有总线的使用,拥有调度的能力,这样才能够及时填补空档,并有效响应其他组件使用总线的需求。
到了这里,就自然明白总线为什么要分类了。分类是为了更好地管理总线,不仅要分,最好是能进一步细分,分类越细,越能在调度时提供更多信息支持,越能物尽其用。
说了这么些关于总线使用的问题,主要是引出一个概念:硬件资源独占时,可以随意使用,但带来问题是使用率低,不经济。如果要共享,就必须有所谓的控制单元,建立规则,进行管理。否则各个用户不仅无法正常完成自己的计算任务,而且还很有可能干扰其他人的计算需求。
1.2 资源管理
如上所述,当需要共享某一硬件资源来达到提高利用率并同时保持良好响应的目标时,就需要有控制单元进行管理。对于计算机硬件整体而言,如独占使用,每次只运行一个计算任务,那么只要在总线这一层实现控制即可。然而如果要运行多个计算任务,或是多个用户共享使用,那就需要一个控制单元来完成管理、调度的功能。而在计算机系统中,这个单元就叫做操作系统。
2. 操作系统
那么不言而喻,操作系统最根本的工作是进行资源管理,确保计算任务可以正确执行。当然任何管理总是有管理理念的差异存在,对应的也就是操作系统调度算法各有侧重。对比操作系统发展史,主要有如下两个方向:
- 追求高CPU利用率,即尽可能填满CPU指令周期。典型的有批处理操作系统、多道操作系统
- 追求低响应时长,即有更好的交互体验。典型的有分时操作系统
这两个方向有各自相违背的点,因为所谓的低响应时长,就代表着必须能够中断执行中的任务,而每次中断,实质上,对于单个任务来讲,都是延长了总执行时长的因素。不过如果能因此服务于更多用户、更多计算任务,甚至更好地将使用到不同组件的任务同时执行,一点点中断开销还是值得的。
2.1 操作系统的定义
道理讲到这里,也不能免俗,需要为操作系统下一个定义。操作系统是一种系统软件,它管理计算机硬件和软件资源,并向计算机应用程序提供通用服务。
换成图示的话,它在整个计算任务中的位置如下所示:
貌似前文中我们只讲到操作系统是管理计算机硬件的,但这里的定义中还出现了软件资源,那么这些软件资源指的又是什么?
我们知道,所谓软件、应用程序这些名词代表的无非是计算任务描述,它从根本上是由CPU ISA中指令加上操作对象有序组合而成。既然核心元素是CPU ISA,而各厂家CPU又有所不同,那么编写程序时,一定需要根据具体ISA去编写。这就带来一个问题,每个软件想要运行在某一CPU上,先要找到手册,逐字逐句进行翻译(指令映射),才能运行。但这些工作其实都是机械重复且低效的,也就意味着要重复地投入大量人力物力来完成这个步骤,然而有一个设备很擅长干这种脏活累活,那就是计算机。如果我们可以将指令映射的步骤自动化,读取CPU ISA手册,自动映射,就无需再手动处理。而这个过程,就是编译器的雏形。
所以软件资源指的是一些基础功能资源,提供一些基础功能,以供编写计算任务描述时使用,简化任务描述的编写时间。而也是因为这些基础软件资源,对底层硬件(如CPU)进行了封装(wrap),才使得操作系统可以提供通用服务。
2.2 操作系统提供了哪些服务
由于个人无法给出准确定义,而又不能误人误己,只能选择翻译大牛书籍,书籍名称为《Operating Systems Internals and Design Principles》 2.1.1小节内容。
通常,一个完整的操作系统需要提供以下几个方面的服务:
-
程序开发
操作系统提供各式各样的工具和服务,如编辑器、调试器,用于帮助程序员开发程序。这些工具按照封装程度可以进一步划分为以下两种:-
Instruction Set Architecture
指令系统体系结构ISA,定义了操作系统使用的机器语言指令系统。事实上,应用程序和操作系统均可以直接访问ISA。 -
Applicaiton Binary Interface
应用程序二进制接口ABI,定义了操作系统的系统调用接口,以及在系统中通过ISA能够使用的硬件资源和服务。每个操作系统或平台会选择使用一种二进制格式作为可执行格式,同一程序如需在不同操作系统上实现可移植,就必须在ABI层进行适配。 -
Application Programming Interface
应用程序编程接口API,API封装了操作系统所提供的硬件资源和服务,使用API可以降低应用程序复杂度,移植时,也可以直接在API层进行映射。
-
-
程序运行
程序运行需要很多步骤,包括加载指令和数据、初始化I/O设备和文件,以及其他相关资源。有了操作系统,程序员只要在编写程序是遵循所提供接口即可,而无需关心执行所需的具体细节。 -
I/O设备访问
同样的,操作系统中可能会同时运行多个程序,程序之间对I/O设备的访问需要管理以便顺利协作。操作系统封装I/O设备的硬件细节,为程序提供统一接口,同时也管理、维护I/O设备使用情况以便调度。 -
文件访问控制
文件从操作系统的角度来看,是I/O设备磁盘上的一种对象。通过对象的抽象,将一组二进制值约束为文件内容,同时通过额外的二进制值来代表各种访问属性。所以文件实际上可以成为磁盘类I/O设备的访问单元,因此,对于I/O设备本身的管理自然包括了内部所有文件情况的维护。 -
系统访问
操作系统管理资源,也维护这大量有关资源的信息。这些信息的访问必须有所保护,否则一旦被恶意修改,轻则系统信息错误,重则直接崩溃。同时,对于同一资源的访问,系统层也应当进行调度,以保证相互间互不冲突。 -
错误检测和响应
计算机硬件终归是电气电路组成的,电气电路在使用环境、寿命等因素的影响下,会出现潜在错误。同时,软件编写中也可能引入错误,如除零。操作系统会对这些潜在错误进行检测,并尝试修复。如无法修复,则提示用户或最终关机。 -
统计信息
对于所有资源的管理调度,需要基于对应的维护信息,只有在各相关组件间共享这些内容,才能更加精确地达成提高CPU利用率或更低响应时长的目标。
3. 操作系统组织架构
上一节中给出了操作系统的定义,列出了需要提供的服务,这一节就从操作系统本身内部如何实现的角度,来谈谈操作系统组织架构。所谓组织架构,实际上就是操作系统中是如何提供各服务的,是每个服务作为一个程序,聚集而形成操作系统,还是走大而全的策略一个程序包含所有操作系统内容。这两种方式,分别对应单内核和微内核两种架构。
3.1 单内核
单内核中所有服务如文件系统、存储管理等都由多个运行在内核态(Kernel Mode)的模块来完成。虽然每个模块单独服务,但由于高度集成,一旦某一模块产生bug,则会使整个内核崩溃。不过同样因为集成度高,所有操作位于同一地址空间内,控制代码的运行效率会更高。
传统UNIX、DOS以及早期的Mac OS系统均采用单内核形式。
3.2 微内核
既然单内核和微内核均有各自优缺点,那么自然而然就能想象得到会有人将两者混合使用。通过让一些微内核结构代码运行在内核空间上,提高内核整体运行效率。典型混合内核例子有Windows NT及之后系列、Mac OS X等。
下图是Windows和Linux操作系统结构图,感兴趣的话可以先有个概念,具体讨论将放在后续文章中。
Linux
4. 总结
本篇定位于介绍操作系统的由来、必要性、所提供的服务,以及服务组织形式。掌握了这些概念,就应该要朝着提高CPU使用率、降低响应时长的目标去,进一步了解内部具体实现原理,而这些,均会在接下来几篇中慢慢道来。
网友评论