这是操作系统进程系列文章第一篇-操作系统发展和进程简介

操作系统的发展

串行处理

对于早期计算机(20世纪40年代后期到20世纪50年代中期),因为没有操作系统,程序员都是直接与计算机硬件打交道。这些机器都在一个控制台上运行,控制台包括显示灯、触发器、某种类型的输入设备和打印机。用机器代码编写的程序通过输入设备载入计算机。如果程序因错误停止,错误原因由指示灯只是。如果程序运行结束,结果将出现在打印机中。

*早期系统主要有两个问题*:

  • 调度: 大多数设备使用一个硬拷贝的登记表预定时间。如果用户预定了一个小时,半小时就运行结束,计算机将闲置30分钟,而如果没有在一个小时内运行结束,程序也会被强制停止。
  • 准备时间:一个程序称为一个作业,运行一个程序可能需要往内存中加载编译器和程序语言,保存编译程序,加载目标程序和公用函数变链接在一起。每一步都可能需要安装拆卸硬件,如果这些步骤出现错误,只能重新开始,会占用太多时间。

这种模式称为串行处理,用户必须顺序访问计算机。

简单批处理系统

早期计算机非常贵,调度和准备又非常浪费时间和资源,为了最大限度的利用处理器,当时的研究人员开发了批处理操作系统。

第一个批处理操作系统(也是第一个操作系统)是20世纪50年代中期由 General Motors 开发的,用在 IBM 701上。

简单批处理方案的中心思想是使用一个称作监控程序的软件。通过使用这类操作系统,用户不再直接访问机器,相反,用户把卡片或磁带中的作业提交给计算机管理员,由他把这些作业按顺序组织成一批,并将整个批作业放在输入设备上,供监控程序使用。每个程序完成批处理后返回到监控程序,同事监控程序自动加载下一个程序。

我们可以从两个角度分析这个方案是如何工作的:

监控程序角度: 监控程序为了能一直控制事件的顺序,需要总是处于内存中并且可以执行。监控程序每次从输入设备中读取一个作业,读入后,当前作业被放置在用户程序区域,并把控制权交给这个作业。作业完成后,控制权交还给监控程序,监控程序再读入下一个作业。

处理器角度: 从这个角度看,处理器执行内存中存储的监控程序的指令,这些指令读入下一个作业并存储到内存中的另一个部分。一旦已经读入一个作业,处理器将会遇到监控程序的分支指令,分支指令指导处理器在用户程序开始处继续执行。处理器继而执行用户程序直到执行结束或者遇到错误。无论哪种情况,处理器都将从监控程序读入下一个指令。

控制权交给作业仅仅意味着处理器当前取和执行的都是用户程序中的指令,而控制权交给监控程序的意思是处理器当前从监控程序中取指令并且执行指令。

监控程序或者批处理操作系统,只是一个简单的计算机程序。它依赖于处理器可以从内存的不同部分取指令的能力,以交替的获取或释放控制权。此外,还要考虑其他硬件功能:

  • 内存保护:当用户程序在运行时,不能改变包含监控程序的内存区域
  • 定时器:用户防止一个作业独占系统。作业开始时,设置定时器,时间到,用户程序将被停止
  • 特权指定:某些指令设计成特权指令,只能由监控程序执行。
  • 中断:早期的计算机模型没有中断能力。这个特征使得操作系统在让用户程序放弃控制权或从用户程序获得控制权时具有更大的灵活性。

多道程序设计批处理(多任务处理)系统

虽然简单的批处理系统可以提供自动作业序列,但由于 I/O 设备处理速度相对于处理器速度太慢,处理器仍然经常空闲。这个时候多道程序设计/多任务处理方案就被提了出来。

它的工作原理是:基于内存空间可以保存操作系统和一个用户程序,假设内存空间容得下操作系统和两个用户程序,那么当一个作业需要等待 I/O 时,处理器可以切换到另一个可能并不在等待 I/O 的作业。进一步还可以扩展存储器以保存三个、四个或更多的程序,并在它们之间进行切换。

多道程序设计实例

多道程序操作系统比单个程序或单道程序系统相对要复杂一些。对准备运行的多个作业,它们必须保存在内存中,这就需要内存管理。此外,如果多个作业都准备运行,处理器还必须决定运行哪一个,这需要某种调度算法。

多道程序设计是为了让处理器和 I/O 设备同时保持忙状态,以实现最大效率。其关键机制是:在响应表示 I/O 事务结束的信号时,操作系统对内存中驻留的不同程序进行处理器切换。

分时系统

通过使用多道程序设计,可以使批处理更加有效,但是对许多作业来说,需要提供一个交互模式,以使用户可以和计算机交互。

因为当时的计算机特别昂贵且巨大,普通用户也买不起,分时操作系统应运而生。

和多道程序设计允许处理器同时处理多个批作业一样,它还可以用于处理多个交互作业。

多个用户分享处理器的时间,因而该技术成为分时。

分时系统中,多个用户可以通过终端同时访问系统,由操作系统控制每个用户程序以很短的时间为单位交替执行。

如果有 n 个用户同时请求服务,若不计算操作系统的开销,每个用户平均只能得到1/n 计算机的有效速度,但由于人的反应时间相对计算机比较慢,所以一个设计良好的操作系统,其响应时间可以接近于计算机的时间。

批处理多道程序设计和分时的比较

项目 批处理多道程序设计 分时
主要目标 充分使用处理器 减小响应时间
操作系统指令源 作业提供的作业控制语言命令 从终端键入的命令

第一个分时操作系统是由麻省理工学院开发的兼容分时系统(CTSS)。系统运行在一台内存为32000个36位字的机器上,常驻程序占用了5000个。当控制权被分配给一个交互用户时,改用户的程序和数据被载入到内存剩余的27000个字的空间中。程序通常在第5000个字单元处开始被载入,系统时钟以大约没0.2秒一个的速度产生中断,在每个中断处,操作系统恢复控制权,并将处理器分配给下一个用户。因此,在固定的时间间隔内,当前用户被剥夺,另一个用户被载入。这项技术称为时间片技术。

操作系统是最复杂的软件之一,操作系统开发中有5个重要的理论进展:进程内存管理信息保护和安全、调度和资源管理、系统结构。

进程

进程的概念是操作系统结构的基础,这个属于最早在20世纪60年代被提出。

关于进程有很多定义:

  • 一个正在执行的程序
  • 计算机中正在运行的程序的一个实例
  • 可以分配给处理器并由处理器执行的一个实体
  • 由单一的顺序的执行线程、一个当前状态和一组相关的系统资源所描述的活动单元

系统程序员在开发早期的多道程序(多任务)和多用户交互系统时(分时)使用的主要工具是中断。一个已定义事件的发生可以暂停任何作业的活动。处理器保留某些上下文(如程序计数器和其他寄存器),然后跳转到中断处理程序中,处理中断,然后恢复用户被中断作业或其他作业的处理。

设计出一个能够协调各种不同活动的系统软件非常困难,也容易出错,一般而言,产生这类错误又4个主要原因:

  1. 不正确的同步:常常会出现这样的情况,一个例程必须挂起,等待系统中其他地方的某一事件。
  2. 失败的互斥:常常出现多个用户或程序试图同时使用一个共享资源的情况。(例如两个用户同时试图编辑文件)
  3. 不正确的程序操作:一个特定的程序结果只依赖与该程序的输入,而并不依赖于共享系统中其他程序的活动。但当程序共享内存并且处理器控制它们交错执行时,它们可能会因为重写相同的内存区域而发生不可预测的相互干扰
  4. 死锁:很可能两个或多个程序相互挂起等待。(单进程 web 应用中相互调用)

解决这些问题需要一种系统级的方法监控处理器中不同程序的执行。进程的概念为此提供了基础。进程可以看做是由3部分组成的:

  • 一段可执行的程序
  • 程序所需的相关数据(变量、工作空间、缓冲区)
  • 程序的执行上下文

最后一部分是根本。执行上下文(execution context)又称做进程状态,是操作系统用来管理和控制进程所需的内部数据。

这种内部信息和进程是分开的,因为操作系统信息不允许被进程之间访问。

上下文包括操作系统管理进程以及处理器正确执行进程所需的所有信息。包括了各种处理器寄存器的内容,汝程序计数器和数据寄存器。它还包括操作系统使用的信息,如进程优先级以及进程是否在等待特定 I/O 事件的完成。

操作系统会给每个进程(包含程序、数据和上下文信息)分配一块存储器区域,并在由操作系统建立和维护的进程表中进行记录。进程表包含记录每个进程的表项,表项内容包括指向包含进程的存储块地址的指针,还包括该进程的部分或全部执行上下文。

  • 进程索引寄存器包含当前正在控制处理器的进程在进程表中的索引。
  • 程序计数器指向该进程中下一条待执行的指令。
  • 基址寄存器和界限寄存器定义了该进程所占的存储器区域:基址寄存器中保存了该存储区域的开始地址,界限寄存器中保存了该区域的大小。

程序计数器和所有的数据引用相对于基址寄存器被解释,并且不能超过界限寄存器中的值,这就可以保护内部进程间不会相互干涉。

下图是一种进程管理的方法:

典型的进程实现方法

在上图中,进程索引寄存器表明进程 B 正在执行。以前执行的进程被临时中断,在 A 中断的同时,所有寄存器的内容被记录在它的执行上下文环境中,以后操作系统就可以执行进程切换,恢复进程 A 的执行。进程切换过程包括保存 B 的上下文和恢复 A 的上下文。当在程序计数器中载入指向 A 的程序区域的值时,进程 A 自动恢复执行。

进程是被当做数据结构来实现的,一个进程可以是正在执行,也可以是等待执行。任何时候整个进程状态都包含在它的上下文环境中。

这一篇主要介绍了操作系统的发展,下篇主要介绍进程的概念以及工作原理。


最后,感谢女朋友支持和包容,比❤️

想了解以下内容可以在公号输入相应关键字获取历史文章: 公号&小程序 | 设计模式 | 并发&协程

关注 赞赏