2 OS结构

  • OS为执行程序提供环境。从内部结构来说,操作系统变化很大,有很多组织方式。
  • 设计一个新的操作系统是个大型任务。
  • 在开始设计前,定义好系统目标非常重要。
  • 所要设计系统的类型决定了如何选择各种算法和策略。

  • 可以从多个角度来研究操作系统。
  • 第一是通过考察所提供的服务。
  • 第二是通过考察为用户和程序员提供的接口。
  • 第三是研究系统的各个组成部分及其相互关系。
  • 本章将从用户角度、程序员角度和操作系统设计人员角度来分别研究操作系统的三个方面。本章
    将硏究操作系统提供什么服务、如何提供服务、设计操作系统的各种方法。最后,介绍如
    何生成操作系统,以及计算机如何启动它的操作系统。

  • 本章目标
  • 介绍操作系统为用户、进程和其他系统提供的服务
  • 讨论组织操作系统的不同方法。
  • 解释如何安装、定制操作系统,及如何启动。

2.1 操作系统服务

2.3系统调用

  • system call提供操作系统提供的有效服务界面。
  • 调用常用C或C++编写,对底层的任务(如必须直接访问的硬件),可能以汇编语言指令的形式提供

  • 讨论OS如何使其系统调用可用前,先看咋使用系统调用:
  • 从一文件读数据并复制到另一文件
  • 输入是两个文件的名称:输入文件和输出文件名。
  • 根据OS设计的不同,这些名称有不同的表示法。
  • 一种方法是程序向用户提问然后得到两个文件名。
  • 对于交互系统
    • 这种方法需要一系列的系统调用:先在屏幕上写出提示信息,再从键盘上读取定义两个文件名称的字符。
  • 对于基于鼠标和基于图标的系统,一个文件名的菜单通常显示在一个窗口中。
    • 用户通过鼠标选择源文件名,另一个类似窗口可以用来选择目的文件名。
    • 这个过程需许多I/O系统调用。

  • 得到文件名后,该程序打开输入文件并创建输出文件。
  • 每个操作都需要另一个系统调用。
  • 每个操作都有可能遇到错误情况。
  • 当程序设法打开输入文件时,它可能发现该文件不存在或者该文件受保护而不能访问。
  • 在这些情况下,程序应该在终端上打印出消息(另一系列系统调用),并且非正常地终止(另一个系统调用)。
  • 如果输入文件存在,那么必须创建输出文件。
  • 用户可能会发现具有同一名称的输出文件已存在。
  • 这种情况可能导致程序中止(一个系统调用),或者必须删除现有文件(另一个系统调用)并创建新的文件(另
    个系统调用)。
  • 对于交互式系统,另一选择是问用户(一系列的系统调用以输出提示信息并从终端读入响应)是否需要替换现有文件或中止程序。

  • 现两个文件都已设置好,可以进入循环以从输入文件中读(一个系统调用)并向输出文件中写(另一个系统调用)。
  • 每个读和写都必须返回一些关于各种可能错误的状态信息。
  • 对于输入,程序可能发现已经到达文件的结東,或者在读过程中发生了一个硬件失败(如
    奇偶检验误差)。
  • 对于写,根据输出设备的不同可能出现各种错误(如没有磁盘空间打印机没纸等)。

  • 最后,整个文件复制完成后,程序关闭两文件(另一个系统调用),在终端或窗口上写一个消息(更多系统调用),最后正常结束(最后的系统调用)。
  • 一个简单的程序也会大量使用操作系统。
  • 通常,系统每秒执行数千个系统调用。
  • 图2.1:这个系统调用序列。

在这里插入图片描述

  • 大多数程序员不会看到这些细节。
  • 开发人员根据API设计程序。
  • API是一系列适用于应用程序员的函数,包括传递给每个函数的参数及其返回的程序员想得到的值。
  • 有三种应用程序员常用的API:适用于 Windows系统的Win32API,
  • 适用于 POSIX系统的 POSX API(包括几乎所有UNX、 Linux和 Mac OS X版本)
  • 用于设计运行于Java虚拟机程序的 Java API。

  • 注意,贯穿本书的系统调用名是常用的例子,每个操作系统都有自己的系统调用命名。

在这里插入图片描述

  • 组成API的函数常为应用程序员调用实际的系统调用。
  • Win32函数Createprocess(生成一个新进程)实际上调用 Windows内核中的 NT Createprocess系统调用。
  • 为什么应用程序员根据API来编程,而不调用系统调用?
  • 根据API编程的好处之一
    • 程序的可移植性,一个采用API设计程序的程序员希望她的程序能在任何支持同样API的系统上编译并执行(尽管事实上,体系的不同常使其很困难)。
    • 此外,对一个应用程序员而言,实际的系统调用比API更注重细节和困难。
  • 尽管如此 ,API中的函数和与其相关的内核系统调用之间还是常常存在紧密的联系。
  • 事实上,许多Win32和POSX的API与UNIX、 Linux和 Windows操作系统提供的自身的系统调用是相类似的。

  • 多数语言的运行时支持系统(与编译器一起的预先构造的函数库)提供了系统调用接口,
    • 作为应用程序与操作系统的系统调用的链接。
  • 系统调用接口截取API的函数调用,并调用操作系统中相应的系统调用。
  • 每个系统调用一个与其相关的数字
    • 系统调用接口根据这些数字维护一个列表索引。
  • 然后,系统调用接口来调用所需的操作系统内核中的系统调用,并返回系统调用状态及其他返回值。

  • 调用者不需知道如何执行系统调用或者执行过程中它做了什么,它只需遵循API并了解执行系统调用后,系统做了什么。
  • 对于程序员,通过API操作系统接口的绝大多数细节被隐藏起来,并被执行支持库所管理。
  • API、系统调用接口和操作系统之间的关系如图2.3,
    • 操作系统如何处理一个调用 opend系统调用的用户应用。

在这里插入图片描述

  • 系统调用根据使用的计算机的不同而不同。
  • 通常,需要提供比所需系统调用识别符更多的信息。
  • 这些信息的具体类型和数量根据特定操作系统和调用而有所不同。
  • 例如,为获取输入,可能需要指定作为源的文件或设备和用于存放输入的内存区域的地址和长度。
  • 当然,设备或文件和长度也可以隐含在调用中。

  • 向操作系统传参有三法。
  • 最简单通过寄存器来传递参数。
  • 参数数量会比寄存器多。这时,这些参数通常存在内存的块和表中,并将块的地址通过寄存器来传递(见图2.4)。
    • Linux和 Solaris就这方法。
  • 参数也可通过程序放在或压入堆栈中,并通过操作系统弾出。
  • 有的系统采用块或堆栈方法,因为这些方法并不限制所传递参数的数量或长度。

在这里插入图片描述

2.4 系统调用类型

  • 在2.4.1到2.4.5,描述操作系统可能提供的系统调用类型。
  • 这些系统调用大多支持后面几章所讨论的有关概念和功能,或被其所支持。
  • 图2.5:OS常提供的系统调用类型

在这里插入图片描述

2.4.1进程控制

  • 运行程序需要能正常或非正常地中断其执行(end或 abort)。
  • 如果一个系统调用被用来非正常地中断执行程序,或者程序运行碰到问题而引起错误陷阱,那么可能会有内存信息转储并产生一个错误信息。
  • 内存信息转储通常写到磁盘上,并被调试器(帮助程序员发现和纠正错误的系统程序)检查和确定问题原因。
  • 不管是正常还是非正常中止,操作系统都必须将控权制转交给调用命令解释器。
  • 命令解释器接着读取下一个命令。
  • 对于交互系统,命令解释器只不过简单地读取下一个命令,因为假定用户会采取合适的命令以处理错误。
  • 对于GUI系统,一个弹出窗口可提醒用户出错并请求建议。
  • 对于批处理系统,命令解释器通常终止整个作业并继续下一个作业。
  • 当出现一个错误的时候,有的系统允许控制卡指出个具体的恢复动作。
  • 控制卡是一个批处理系统概念,它是一个管理进程执行的命令。
  • 如果程序发现输入有错并想要非正常地终止,那么它可能也需要定义一个错误级别。
  • 更加严重的错误可用更高级的错误参数来表示。
  • 如果将正常终止定义为级别为0的错误,那么可能将正常和非正常终止混合起来。
  • 命令解释器和下一个程序能利用错误级别来自动决定下一个动作。

  • 执行一个程序的进程或作业可能需要装入和执行另一个程序。
  • 这一点允许命令解释器来执行一个程序,该命令可通过用户命令、鼠标单击或批处理命令来表示。
  • 当装入程序终止时,一个有趣的问题是控制权返回到哪里。
  • 这个问题与现有程序是否丢失、保存或与新程序继续并发执行有关。

  • 如果新程序终止时控制权返回到现有程序,那么必须保存现有程序的内存映像。
  • 因此,事实上创建了一个机制以便一个程序调用另一个程序。
  • 如果两个程序并发继续,那么创建了一个新作业和进程以便多道执行。
  • 通常,有的系统调用专门用于这一目的(如 createprocess或 submit job)。

here!!!

2.5 系统程序

here!!!

2.6 操作系统设计和实现

2.7 操作系统结构

  • 现代OS庞大而复杂,为能正常工作并易修改,须认真设计。
    • 方法是将这一任务分成小模块而不只是一个单块系统。
    • 每个模块都应该是明确定义的系统部分,有明确定义的输入、输出和功能。
  • 1章中简要讨论操作系统的常用模块,
    • 本节讨论这些模块如何连接起来以组成内核

2.7.1 简单结构

  • 许多商业系统没有明确定义的结构。
  • 通常,这些操作系统最初是较小、简单且功能有限的系统,但后来渐渐超过了其原来的范围。
  • MS-DOS就是一个这样的操作系统。
  • 最初由几个人设计实现,当时没想到它如此受欢迎。
  • 它主要是利用最小的空间提供最多的功能,因此它并没有被仔细地划分成模块。
  • 图2.10显示其结构。

  • MS-DOS中,没有很好地区分接口和功能层次。
  • 应用程序能访问基本的I/O子程序,直接写到显示器和磁盘驱动程序中。
  • 这种任意性使MS-DOS易受错误(恶意)程序的伤害,导致用户程序出错时整个系统崩溃。
  • MS-DOS受限于同时代的硬件, Intel8088未提供双模式和硬件保护,
    • MS-DOS设计者除了允许基本的硬件的访问外,没有选择

在这里插入图片描述

  • 另个受限结构的例子是原始的UNX。
  • UNX是另一个最初受到硬件功能限制的系统。
  • 它由内核和系统程序两个独立部分组成。
  • 内核进一步分成为一系列接口和驱动程序,这些年随着UNX的发展,这些程序被不断地增加和扩展。
  • 可以将传统的UNX操作系统分层来研究。
  • 如图2.11,物理硬件之上和系统调用接口之下的所有部分作为内核。
  • 内核通过系统调用以提供文件系统、CPU调度、内存管理和其他OS功能。
  • 总的来说,这一层里面组合了大量的功能。
  • 这种单一式结构使得UNIX难以增强。

在这里插入图片描述

2.7.2 分层方法

  • 采用适当硬件支持,OS可分成比
    • 原来MS-DOS和UNIX所允许的更小和更合适的模块。
  • 这样os能提供对计算机和使用计算机的应用程序更多的控制。
  • 实现人员能更加自由地改变系统的内部工作和创建模块操作系统。
  • 采用自顶向下方法,可先确定总的功能和特征,再划分成模块。
  • 隐藏信息同样很重要,因为它在保证子程序接口不变和子程序本身执行其功能的前提之下,允许程序员自由地实现低层函数。

  • 系统模块化有许多方法。
  • 一种方法是分层法,即OS分成若干层(级)。
  • 最底层(层0)为硬件,最高层(层N)为用户接口。
  • 分层结构如图2.12。

在这里插入图片描述

here!!!

2.10系统启动

  • 生成OS之后,它必须要为硬件所用。
  • 硬件咋知内核在哪,咋装入内核?
    • 装入内核以启动计算机的过程称为引导系统。
  • 大多数计算机系统都有小块代码,
    • 引导程序或引导装载程序。
    • 它能定位内核,将它装入内存,开始执行。
  • 如PC,用两步完成:
    • 一个简单的引导程序从磁盘上调入一个较复杂的引导程序,后者再装入内核。

  • CPU收到一个重置事件时,
    • 如被加电或重启,
    • 具有预先定义内存位置的指令寄存器被重新装载,并在此开始执行。
    • 该位置就是初始引导程序的所在。
  • 该程序为只读存储器(ROM)形式,因为系统启动时RAM处未知态。
  • 由于不需初始化和不受计算机病毒的影响,用ROM很方便。

  • 引导程序可完成一系列任务。
  • 通常,一个任务要运行诊断程序来确定机器的状态。
  • 如果诊断通过,程序可按启动步骤继续进行。
  • 系统的所有部分都可以被初始化,从CPU寄存器到设备控制器,以及内存的内容。
  • 最后,OS得以启动。

  • 有些系统(如手机、PDA和游戏控制台)在ROM中保存完整的OS。
  • 在ROM中存储完整的操作系统特别适合小型OS,它支持简单的硬件和操作。
  • 该方法的问题是,改变引导程序代码要改变ROM芯片。
  • 有些系统通过使用可擦写只读存備器( EPROM)来解决此问题,
    • 它是一个只读存储器,只有当明确给定一个命令时才会变为可写。
  • 所有形式的ROM都是固件,它们的特征介于硬件与软件之间。
    • 固件存在的问题是在此执行代码比在RAM中慢。
    • 有些系统将操作系统存储在固件中,并将之复制在RAM中以获得更快的执行速度。
    • 固件的最后一个问题是它相对较贵,所以用得少。

  • 对大型OS(如 Windows、 Mac OS X和UNX)或经常改变的系统,
    • 引导程序存固件中,OS存磁盘。
  • 引导程序运行诊断程序,它具有能够从磁盘固定位置(0区块)读取整块信息到内存的代码,并从引导块执行代码。
  • 存储在引导块的程序复杂,可将一个完整的OS装载到内存并开始执行。
  • 更典型的是,代码很简单(适合于单磁盘区块),仅知道在磁盘上的地址以及引导程序余下的长度信息。
  • 所有这些磁盘绑定的引导程序和操作系统本身可以通过向磁盘写入新的版本,从而很容易进行改变。
  • 具有引导分区(见12.5.1节)的磁盘被称为引导磁盘或系统磁盘。

  • 既然完全的引导程序已被装入,它可以扫描文件系统以找到操作系统内核,将之装入内存,启动并执行。只有到了这个时候才能说系统开始运行了

2.11 小结

  • 操作系统提供若干服务。
  • 在最底层,系统调用允许运行程序直接向操作系统发出请求在高层,命令解释程序或Shel提供了一个机制以便用户不必编写程序就能发出请求。
  • 命令可来自文件(批处理模式),或者直接来自键盘输入(交互模式或分时模式)。
  • 系统程序用来满足一些常用用户操作。

  • 请求类型随请求级别而变化。系统调用级别提供基本功能,如进程控制、文件和设备
    管理。由命令解释程序或系统程序来完成的高级别请求需要转换成一系列的系统请求。系
    统服务可分成许多类型:程序控制、状态请求和1/O请求。程序出错可作为对服务的一种
    隐式请求。

  • 定义了系统服务之后,就可开发操作系统的结构。
  • 需要用各种表记录一些信息,这些信息定义了计算机的系统状态和系统的作业状态
    设计一个新操作系统是一项重大任务。在设计开始之前,定义好系统目标是很重要的。
    系统设计的类型是作为选择各种必要算法和策略的基础。

  • 由于OS大,所以模块化很重要。
  • 按一系列层或采用微内核来设计系统是比较好的技术。
  • 虚拟机概念采用了分层方法,并将操作系统内核和硬件都作为硬件来考虑。
  • 其他操作系统可以建立在这一虚拟机之上

  • 实现JVM的任何OS能运行所有Java程序,
    • JVM为Java程序抽象化了底层系统,提供平台无关接口。

  • 在整个OS设计周期中,须仔细区分策略决定和实现细节(机制)。
  • 在后面需要修改策略时,这种区分允许最大限度的灵活性。

  • 现在OS几乎都用系统实现语言或高级语言编写。
  • 这改善了操作系统的实现、维护和可移植性。
  • 为特定机器配置并创建操作系统,必须执行系统生成。

  • 为运行计算机系统,必须初始化CPU和在固件系统中启动执行引导程序。
  • 如果OS也在固件系统中,引导程序可以直接启动操作系统。
  • 否则,它必须完成这样一道程序:
    • 逐步地从固件或磁盘装载更聪明的程序,直到OS本身被装入内存并执行。

习题

发布了447 篇原创文章 · 获赞 249 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/zhoutianzi12/article/details/103553099
os2