Java笔记··By/蜜汁炒酸奶

信马由缰操作系统-闲话进程的生命周期

全都写到重学java中有点大,后期分专题不太容易,所以打算细分出来看看效果。上文说到进程是动态的,自然就会有开始-结束的生命周期。这里以 汤子瀛版《计算机操作系统(慕课版)》为主线串联记录一下,方便后期相关讨论。

mindmaster_os_state.png

1. 进程的基本状态

一般而言,每个进程至少会处于就绪(ready)、执行(running)、阻塞(block)三种基本状态中的一个,而为了满足进程控制块对数据与操作的完整性要求以及增强管理的灵活性,通常系统也会引入创建状态和终止状态。最终组成了目前常见的五种基本状态。

  • 创建(new)状态 :有些地方也叫new或者新建状态。此时进程正在创建,当一个进程被创建时,如果所需资源尚且无法得到满足,此时就处于创建状态。
  • 就绪(ready)状态 :进程已经准备好执行的状态,此时进程已获取到了除CPU以外的所有必需资源。
  • 执行(running)状态 :也称运行状态,指进程获取到了CPU后其进程“正在执行”这一状态。此时进程中的指令正在执行。
  • 阻塞(block)状态 :也称等待(waiting)状态,进程因某些事件(如I/O操作或者某项资源暂时获取失败)导致执行受到了阻塞,无法继续执行,此时调度系统会将CPU调度给另一个就绪的进程,而让受阻的的进程处于暂停状态。
  • 终止(terminated)状态 :进程执行完成的状态。此时可能已经正确完整的执行,也可能是出现了无法克服的错误,或者被OS或其它有终止权限的进程所终止。当进程进入终止状态便不可再次执行。进程的终止需要:
    • 1.等待OS进行善后操作。
    • 2.将进程的PCB清零并将PCB空间返回OS。

一次只有一个进程可在一个处理器上运行(running)。但许多进程可处于就绪(ready)或阻塞(block)状态。

进程五种基本状态转换图

2. 挂起操作引入与状态转换

除了以上基本状态,有些系统会有更细的划分,比如在引入挂起操作之后。当该操作作用于某个进程时,该进程将被挂起,从动态变成静态。其对应的激活会将静态转回动态。

2.1 引入原因:

在许多系统中为了满足系统和用户观察与分析进程的需要而引入,具体如下:

  • 终端用户的需求 :终端用户自己的程序在运行期间发现有可疑的问题,希望暂停程序运行以便排查和修改。
  • 父进程的需求 :有时候父进程希望挂起自己的某个子进程,以便考察与修改该子进程或者协调子进程间的活动。
  • 负荷调节的需求 :当实时系统中的工作负荷较重,可能影响到对实时任务的控制时,可以把一些不重要的进程挂起,保证自身正常运行。
  • OS的需求 :OS有时候希望挂起某些进程,以便检查在进程运行期间资源的使用情况或进行记账等。

2.2 引入后的状态变更

在引入挂起原语 Suspend 和激活原语 Active(两者必须成对使用)后,在两者的共同作用下,成功将状态转换变得更复杂。

  • 创建状态:此时与原有创建状态相同。
  • 创建->活动就绪进程处于未挂起的就绪状态,称为活动就绪,表示为Readya。在当前系统的性能和内存容量均允许的情况下,完成创建进程的必要操作后,相应地系统会将进程状态转为活动就绪状态,此时进程可以接收调度。
  • 创建->静止就绪当活动就绪的进程被挂起后,变成了静止就绪,表示为Readys。当系统资源不足以完成进程创建时,系统不会分配给新建进程所需的资源(主要是内存),相应地系统会将进程状态转为静态就绪状态。进程被安置在外存,不参与调度,此时进程创建工作尚未完成。相当于把就绪状态进行了细分。
  • 活动就绪->静止就绪 :处于活动就绪的进程,若用挂起原语将其挂起,则该进程的状态将会转为静止就绪状态。
  • 静止就绪->活动就绪 :处于静止就绪的进程,若用激活原语将其激活,则该进程的状态将会转为活动就绪状态。
  • 活动阻塞->静止阻塞进程处于未被挂起的阻塞状态被称为活动阻塞,表示为Blockeda当用挂起原语将该进程挂起后,进程的状态便转成了静止阻塞状态,表示为Blockeds。处于该状态的进程再其所期待的事件发生后,将从静止阻塞转为静止就绪。
  • 静止阻塞->活动阻塞 :处于静止阻塞状态的进程,若用激活原语将其激活,该进程会从静止阻塞转为活动阻塞。当其所期待的事件发生后,将从活动阻塞转为活动就绪。
  • 执行->终止 :与原有终止相同。

引入挂起后进程状态转换图

3. 进程控制

上面介绍了进程拥有的状态和转换过程,这里详细说下相关产生状态的事件。

3.1 进程的创建

在OS中,允许一个进程创建另一个进程,通常把创建进程的进程称为父进程(parent process),被创建的进程称为子进程(progeny process)。子进程可以继续创建自己的子进程(即父进程的孙进程),由此进程及其子孙进程共同形成了进程的层次结构,最终组成的是一棵有向树形,常称为进程树

3.1.1 引起进程创建的事件

为了使多个进程并发执行,需要先为它们分别创建各自的进程,涉及典型的创建事件有4种:

  1. 用户登录 :在分时系统中,用户在终端键入登录命令后,若登录成功,系统会为用户创建一个进程,并将其插入就绪队列中。
  2. 作业调度 :在多道批处理系统中,当作业调度程序按一定算法调度到某个(某些)作业时,便会将它们装入内存,并创建一个进程,将其插入就绪队列中。
  3. 提供服务 :当运行中的用户程序提出某种请求后,系统将专门创建一个进程来为用户程序提供其所需服务,如当需要打印功能时,单独创建一个打印进程,使用户进程和打印进程可以并发进行。
  4. 应用请求 :上述三种都是系统内核为用户程序创建一个新进程,而对于“应用请求”这类事件需由用户进程自己创建新进程,以使新进程可以同创建进程并发执行共同完成特定任务。如从键盘等输入设备获取数据,通过数据处理后展示到屏幕上,可以拆成获取数据的进程和数据处理的进程/数据输出进程从而提升任务完成速度。

3.1.2 进程创建过程

每当要创建一个新进程时,OS便调用进程创建原语,并按如下步骤创建一个新的进程:

  1. 申请空白PCB :为新进程申请一个唯一的数字标识符,并从 PCB 集合中索取一个空白 PCB。
  2. 为新进程分配其运行所需资源 :包括各种物理和逻辑资源,如内存、文件、I/O设备和CPU时间等,这些资源从其父进程获得。新资源对这些资源的需求一般也要提前告知OS和父进程。如,为新进程的程序和数据以及用户栈分配必要的内存空间时,OS必须提前知道新进程所需内存大小:
    • 对于批处理作业,其大小可在用户提出创建进程要求时提供。
    • 对于为应用进程创建子进程,需要在该进程提出创建进程的请求中给出。
    • 对于交互型作业,用户可以不给出内存要求而由系统分配一定的内存空间,如果新进程需要共享已载入内存的共享段(即内存中的某个地址空间),则必须建立相应的链接。
  3. 初始化PCB :PCB的初始化工作包括:
    • 初始化标志信息,将系统分配的标识符和父进程标识符填入新 PCB 中。
    • 初始化处理机状态信息,使程序计数器指向程序的入口地址,使栈指针指向栈顶。
    • 初始化处理机控制信息,将进程的状态设置为就绪状态或者静止就绪状态。
    • 优先级设置,通常需要将其设置为最低优先级,除非用户以显示方式提出高优先级要求。
  4. 将新进程插入就绪队列 :若进程就绪队列能够接纳新进程,就将新进程插入就绪队列。

当进程创建新进程时,有两种执行的可能

  • 父进程与子进程并发执行。
  • 父进程等待,直到其某个或全部子进程执行完毕。
    新进程的地址空间也有两种可能
  • 子进程是父进程的复制品(即子进程具有和父进程相同的程序和数据),如后续要提到的Unix中的线程与进程的关系。
  • 子进程加载另一个新进程,如Unix中的父进程与子进程的关系,子进程通过执行系统调用exec()来用新程序取代进程空间。

3.2 进程的终止

3.2.1 引起进程终止的事件

终止事件也比较好理解,简单来说就是正常执行完成、遇到报错终止、外界人员通过kill等强制干预。

  1. 正常结束 :表示进程的任务已经完成,准备退出运行。任何系统中都应有一个用于表示进程已经运行完成的指示//指令。
  2. 异常结束 :进程运行时发生了某种异常事件,使程序无法继续执行。常见的异常事件有:
    • 越界异常 :程序访问的存储区域已经越出所占存储区域的范围,如数组访问越界。
    • 保护异常 :进程试图去访问一个不允许访问的资源或者文件,或以不适当的方式进行访问,如进程试图去写一个只读文件。
    • 指令异常 :程序试图去执行一个不存在的指令(非法指令),出现该异常的原因可能是程序错误的转移到了数据区,把数据当成了指令。
    • 特权指令异常 :进程试图去执行一条只允许OS执行的指令。
    • 运行超时 :进程的运行时间超过了设定的最大值。
    • 等待超时 :进程等待某个时间的时间超过了指定的最大值。
    • 算数运算异常 :进程试图去执行一个被禁止的运算,如被0除。
    • I/O异常 :I/O过程中发生了错误等。
  3. 外界干预 :进程应外界的请求而终止运行。
    • 操作员或者OS干预 :如果系统中发生了某事件如系统死锁等,需要由操作员或者OS采取终止某些进程的方式把系统从死锁状态中解救出来。
    • 父进程请求 :子进程完成父进程所要求的任务时,父进程可以提出请求以结束子进程。
    • 父进程终止 :当父进程终止时,它所有的子孙进程都应当结束。因此OS在终止父进程时会将其所有的子孙进程终止。

3.2.2 进程的终止过程

当发生了终止事件后,OS便会调用终止原语,按下面步骤终止进程:

  1. 检索PCB并获取其状态信息 :根据被终止进程的标识符,从PCB集合中检索出该进程的PCB,并从该进程的PCB中读取该进程的状态。
  2. 终止进程并更新调度标志 :若被终止的进程正处于执行状态,则立即终止该进程的执行,并置调度标志为真,以指示该进程被终止后应重新进行调度。
  3. 终止子孙进程 :若该进程存在子孙进程,则还应终止其所有子孙进程,以防止它们成为不可控的进程。
  4. 归还资源 :将被终止的进程所拥有的所有资源归还其父进程,或者归还给系统。
  5. 将PCB从队列移出 :将被终止进程的PCB从所在队列(或链表)中移出,等待其它程序来搜集信息。

3.3 进程的阻塞与唤醒

3.3.1 引起进程阻塞与唤醒的事件

  1. 向系统请求共享资源失败:当向系统请求共享资源时由于系统没有足够的资源进行分配,进程会因得不到资源而进入阻塞状态,当其它进程释放等情况发生从而得到足够的资源时该进程才会被唤醒。
  2. 等待某种操作的完成 :当进程启动某个操作后,如果需要等待该操作完成之后才能继续执行,此时就会进入阻塞状态,直到对应操作完成才会被唤醒,如阻塞I/O操作。
  3. 新数据尚未到达 :对于相互合作的进程,如果一个进程需要先得到另一个进程提供的数据后才能对该数据进行处理,则只要数据尚未到达就会一直处于阻塞状态。
  4. 等待新任务的到达 :在某些OS中往往会设定一些特定的系统进程,每当任务完成变将自己阻塞起来,等待新的任务的到来。如网络系统中的数据包发送与接收。

3.3.2 进程的阻塞过程

正在执行的进程,发生上面事件后,进程变会调用阻塞原语block将自己阻塞,从而可见其是自身的一种主动行为。进入阻塞状态后,按如下步骤进行阻塞:

  1. 系统停止执行的进程,将 PCB 中的现行状态由执行转为阻塞。
  2. 将 PCB 插入到阻塞队列,如果设置了因不同事件而阻塞的多个阻塞队列,则应插入到具有相同事件的的队列中。
  3. 转至调度程序进行重新调度操作,将处理机分配给另一个就绪进程并进行切换。即保留被阻塞进程的处理机状态,并按新进程的 PCB 中的处理机状态设置 CPU 的环境。

3.3.2 进程的唤醒过程

当进程所期待的事件发生时,有关进程会调用唤醒原语wakeup以将等待该事件的进程唤醒,其执行过程是:

  1. 把被阻塞的进程从等待该事件的阻塞队列中移出。
  2. 将该进程 PCB 中的现行状态由阻塞改为就绪。
  3. 将该 PCB 插入就绪队列中。

3.4 进程的挂起与激活

关于相关事件可参考上面【2. 挂起操作引入与状态转换】中的引入原因。

3.3.2 进程的挂起过程

当系统出现引发进程挂起事件时,系统会利用挂起原语suspend将指定进程或者处于阻塞状态的进程挂起,其执行过程如下:

  1. 检测被挂起进程的状态,若为活动就绪状态,则将其改为静止就绪状态
  2. 针对活动阻塞的进程,将其改为静止阻塞状态
  3. 将该进程的 PCB 复制到某指定的内存区域,为方便用户或父进程考查该进程的运行情况。
  4. 若被挂起的进程正在执行,则转向调度程序重新调度。

3.3.2 进程的激活过程

当系统出现激活进程的事件时,OS会利用激活原语active将指定的进程激活,过程如下:

  1. 将进程从外存调入内存,检测该进程的现行状态,若静止就绪,则改为活动就绪,若静止阻塞,则改为活动阻塞。
  2. 若采用抢占调度策略,则每当有静止就绪进程被激活而插入就绪队列时,便应检查是否要进行重新调度。即由调度程序将被激活进程与当前进程两者优先级进行比较:
    • 若被激活的进程优先级较低,则不必重新调度。
    • 反之,立即终止当前进程的运行,并把处理机分配给刚被激活的进程。

4 主要参考资料

  1. 《计算机操作系统(慕课版)》汤子瀛等
  2. 《操作系统概念(原书第9版)》
预览
Loading comments...
0 条评论

暂无数据

example
预览