深入理解进程

为什么会产生进程概念

所有现代的计算机经常会在同一时间做许多件事,在任何多道程序设计系统中,CPU由一个进程快速切换至另一个进程,使每个进程各运行几十或几百个 毫秒。严格地说,在某一个瞬间,CPU只能运行一个进程。但在1秒钟期间,它可能运行多个进程,这样就 产生并行的错觉。有时人们所说的伪并行就是指这种情形,以此来区分多处理器系统(该系统有两个或多个 CPU共享同一个物理内存)的真正硬件并行。人们很难对多个并行活动进行跟踪。因此,经过多年的努力, 操作系统的设计者发展了用于描述并行的一种概念模型(顺序进程),使得并行更容易处理

进程模型

在进程模型中,计算机上所有可运行的软件,通常也包括操作系统,被组织成若干顺序进程 (sequential process),简称进程(process)。一个进程就是一个正在执行程序的实例,包括程序计数器、 寄存器和变量的当前值。
从概念上说,每个进程拥有它自己的虚拟CPU。当然,实际上真正的CPU在各进程之间来回切换

如图所示:
在这里插入图片描述
在一台多道程序计算机的内存中有4道程序。在图中,这4道程序被抽象为4 个各自拥有自己控制流程(即每个程序自己的逻辑程序计数器)的进程,并且每个程序都独立地运行。当 然,实际上只有一个物理程序计数器,所以在每个程序运行时,它的逻辑程序计数器被装入实际的程序计数 器中。当该程序执行结束(或暂停执行)时,物理程序计数器被保存在内存中该进程的逻辑程序计数器中。 在图中我们看到,在观察足够长的一段时间后,所有的进程都运行了,但在任何一个给定的瞬间仅有一 个进程真正在运行。

进程和程序间的区别

进程和程序间的区别是很微妙的,但非常重要,我们可以举个例子,假如一个父亲在做蛋糕,他有做蛋糕的食谱,有做蛋糕所需要的材料(如鸡蛋,面粉,糖,香料等),在这个比喻中,父亲就是处理器(CPU),食谱就是程序(即用适当形式描述的算法),而做蛋糕的各种原料就是输入数据。进程就是厨师阅读食谱、取来各种原料以及烘制蛋糕等一系列动作的总和

现在假设儿子跑过来跟父亲说他受伤了,然后父亲记录下他照着食谱做到哪儿了(保存进程的当前状态),然后拿出一本急救手册,按照其中的指示处理伤口,这里,我们看到处理机从一个进程(做蛋糕)切换到另一个高优先级的进程(实施医疗救治),每个进程拥有各自的程序(食谱和急救手册)。当伤口处理完之后,父亲又回来做蛋糕,从他离开时的那一步继续做下去

关键思想:

  • 一个进程是某种类型的一个活动,它有程序、输入、输出以及状态。单个处理器可以被若干进程共享,它使用某种调度算法决定何时停止一个进程的工作,并转而为另一个进程提供服务

创建进程

操作系统需要有一种方式来创建进程。一些非常简单的系统,即那种只为运行一个应用程序设计的系统 (例如,微波炉中的控制器),可能在系统启动之时,以后所需要的所有进程都已存在。然而在通用系统中,需要有某种方法在运行时按需要创建或撤销进程。

有4种主要事件导致进程的创建:

  • 系统初始化
    启动操作系统时,通常会创建若干个进程。其中有些是前台进程,也就是同用户(人类)交互并且替他 们完成工作的那些进程。其他的是后台进程,这些进程与特定的用户没有关系,相反,却具有某些专门的功能。例如,设计一个后台进程来接收发来的电子邮件,这个进程在一天的大部分时间都在睡眠,但是当电子邮件到达时就突然被唤醒了,停留在后台处理诸如电子邮件、Web页面、新闻、打印之类活动的进程称 为守护进程(daemon)。在大型系统中通常有很多守护进程,在Windows中,可使用任务管理器
  • 执行了正在运行的进程所调用的进程创建系统调用
    一个正在运行的进程经常发出系统调用,以 便创建一个或多个新进程协助其工作。在所要从事的工作可以容易地划分成若干相关的但没有相互作用的进 程时,创建新的进程就特别有效果。例如,如果有大量的数据要通过网络调取并进行顺序处理,那么创建一 个进程取数据,并把数据放入共享缓冲区中,而让第二个进程取走数据项并处理之,应该比较容易。在多处 理机中,让每个进程在不同的CPU上运行会使整个作业运行得更快
  • 用户请求创建一个新进程
    在交互式系统中,键入一个命令或者点(双)击一个图标就可以启动一个程序。这两个动作中的任何一 个都会开始一个新的进程,并在其中运行所选择的程序
  • 一个批处理作业的初始化
    形仅在大型机的批处理系统中应用。用户在这种系统中(可能是远程地)提交批 处理作业。在操作系统认为有资源可运行另一个作业时,它创建一个新的进程,并运行其输入队列中的下一作业

从技术上看,在所有这些情形中,新进程都是由于一个已存在的进程执行了一个用于创建进程的系统调 用而创建的。这个进程可以是一个运行的用户进程、一个由键盘或鼠标启动的系统进程或者一个批处理管理 进程。这个进程所做的工作是,执行一个用来创建新进程的系统调用。这个系统调用通知操作系统创建一个 新进程,并且直接或间接地指定在该进程中运行的程序

进程的终止

进程在创建之后,它开始运行,完成其工作。但永恒是不存在的,进程也一样。迟早这个新的进程会终 止,通常由下列条件引起:

  • 正常退出(自愿的)
    多数进程是由于完成了它们的工作而终止。当编译器完成了所给定程序的编译之后,编译器执行一个系 统调用,通知操作系统它的工作已经完成
  • 出错退出(自愿的)
    比如,要编译程序fang.c,但这个文件并不存在,于是编译器就会退出,在给出了错误参数时,面向屏幕的交互式进程通常并不退出。相反,这些程序会弹出一个对话框,并要求用户再试一次。
  • 严重错误(非自愿)
    通常是由于程序中的错误所致。例如,执行了一条非法指令、引用不存在的内存,或除数是零等
  • 被其他进程杀死(非自愿)
    某个进程执行一个系统调用通知操作系统杀死某个其他进程

进程的层次结构

某些系统中,当进程创建了另一个进程后,父进程和子进程就以某种形式继续保持关联。子进程自身可 以创建更多的进程,组成一个进程的层次结构。请注意,这与植物和动物的有性繁殖不同,进程只有一个父进程

Windows中没有进程层次的概念,所有的进程都是地位相同的。惟一类似于进程层次的暗示是在 创建进程的时侯,父进程得到一个特别的令牌(称为句柄),该句柄可以用来控制子进程。但是,它有权把 这个令牌传送给某个其他进程,这样就不存在进程层次了

进程的状态

尽管每个进程是一个独立的实体,有其自己的程序计数器和内部状态,但进程之间经常需要相互作用。 一个进程的输出结果可能作为另一个进程的输入

当一个进程在逻辑上不能继续运行时,它就会被阻塞,典型的例子是它在等待可以使用的输入。还可能有这样的情况:一个概念上能够运行的进程被迫停止,因为操作系统调度另一个进程占用了CPU。这两种情 况是完全不同的。在第一种情况下,进程挂起是程序自身固有的原因(在键入用户命令行之前,无法执行命 令)。第二种情况则是由系统技术上的原因引起的(由于没有足够的CPU,所以不能使每个进程都有一台它私用的处理器)
在这里插入图片描述
在图中可以看到显示进程的三种状态的状态图。这三种状态是:

  • 运行态(该时刻进程实际占用CPU)
  • 就绪态(可运行,但因为其他进程正在运行而暂时停止)
  • 阻塞态(除非某种外部事件发生,否则进程不能运行)

转换2和3是由进程调度程序引起的,进程调度程序是操作系统的一部分,进程甚至感觉不到调度程序的 存在。系统认为一个运行进程占用处理器的时间已经过长,决定让其他进程使用CPU时间时,会发生转换 2。在系统已经让所有其他进程享有了它们应有的公平待遇而重新轮到第一个进程再次占用CPU运行时,会 发生转换3。调度程序的主要工作就是决定应当运行哪个进程、何时运行及它应该运行多长时间

当进程等待的一个外部事件发生时(如一些输入到达),则发生转换4。如果此时没有其他进程运行, 则立即触发转换3,该进程便开始运行。否则该进程将处于就绪态,等待CPU空闲并且轮到它运行

使用进程模型使得我们易于想象系统内部的操作状况。一些进程正在运行执行用户键入命令所对应的程 序。另一些进程是系统的一部分,它们的任务是完成下列一些工作:比如,执行文件服务请求、管理磁盘驱 动器和磁带机的运行细节等。当发生一个磁盘中断时,系统会做出决定,停止运行当前进程,转而运行磁盘 进程,该进程在此之前因等待中断而处于阻塞态。这样,我们就可以不再考虑中断,而只是考虑用户进程、 磁盘进程、终端进程等。这些进程在等待时总是处于阻塞状态。在已经读入磁盘或键入字符后,等待它们的 进程就被解除阻塞,并成为可调度运行的进程

进程的实现

为了实现进程模型,操作系统维护着一张表格(一个结构数组),即进程表(process table)。每个进 程占用一个进程表项,该表项包含了进程状态的重要信息,包括程序计数器、堆栈指针、内存分配状况、所打开文件的状态、账号和调度信息,以及其他在进程由运行态转换 到就绪态或阻塞态时必须保存的信息,从而保证该进程随后能再次启动,就像从未被中断过一样

在这里插入图片描述

图中展示了在一个典型系统中的关键字段。第一列中的字段与进程管理有关。其他两列分别与存储 管理和文件管理有关。应该注意到进程表中的字段是与系统密切相关的,不过该图给出了所需要信息的大致介绍

在了解进程表后,就可以对在单个(或每一个)CPU上如何维持多个顺序进程的错觉做更多的阐述。与 每一I/O类关联的是一个称作中断向量(interrupt vector)的位置(靠近内存底部的固定区域)。它包含中断 服务程序的入口地址。假设当一个磁盘中断发生时,用户进程3正在运行,则中断硬件将程序计数器、程序 状态字,有时还有一个或多个寄存器压入堆栈,计算机随即跳转到中断向量所指示的地址。这些是硬件完成 的所有操作,然后软件,特别是中断服务例程就接管一切剩余的工作

所有的中断都从保存寄存器开始,对于当前进程而言,通常是在进程表项中。随后,会从堆栈中删除由 中断硬件机制存入堆栈的那部分信息,并将堆栈指针指向一个由进程处理程序所使用的临时堆栈。一些诸如 保存寄存器值和设置堆栈指针等操作,无法用C语言这一类高级语言描述,所以这些操作通过一个短小的汇 编语言例程来完成,通常该例程可以供所有的中断使用,因为无论中断是怎样引起的,有关保存寄存器的工 作则是完全一样的

当该例程结束后,它调用一个C过程处理某个特定的中断类型剩下的工作。(假定操作系统由C语言编 写,通常这是所有真实操作系统的选择)。在完成有关工作之后,大概就会使某些进程就绪,接着调用调度 程序,决定随后该运行哪个进程。随后将控制转给一段汇编语言代码,为当前的进程装入寄存器值以及内存映射并启动该进程运行

中断发生后操作系统最底层的工作步骤:
在这里插入图片描述
当该进程结束时,操作系统显示一个提示符并等待新的命令。一旦它接到新命令,就装入新的程序进内 存,覆盖前一个程序

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值