213_进程控制
# 2.1_3_进程控制
各位同学大家好,在这个小节中我们会学习进程控制相关的知识点,首先我们会介绍什么是进程控制,应该怎么实现。进程控制它是由原语来实现的,那么之后我们又会介绍实现进程控制相关的这些原语都有哪些,那么我们按照从上至下的顺序依次讲解。
# 进程控制
首先来看一下什么是进程控制,在咱们的王道书上给出了一个定义,进程控制的主要功能其实就是对系统中的所有进程实施有效的管理,它具有创建新的进程,撤销进程,实现进程状态转换等功能,这个比较复杂,那么我们可以把进程的控制简单的理解为就是要实现各种进程状态之间的转换,包括从创建态到就绪态,或者从就绪态到终止态这样的一系列的转换。所以其实进程控制其实就是要实现这些绿色箭头表示的这些具体的过程
那么我们应该如何实现这种进程控制,怎么实现这些进程状态之间的转换?我们先来回顾一下之前提到的有一个叫做进程组织的问题,操作系统会把各个处于不同状态的进程对应的 PCB 挂到相应的一系列的队列当中,用这种方式来管理组织进程的 PCB,
那么我们再把这个模型再来细化一下,就像这个样子
如果一个进程要被创建,那么它会处于创建它创建进程的过程,需要对进程的 PCB 进行初始化,然后分配像内存之类的系统资源。
当进程创建完毕之后,初始化这些工作结束之后,会把进程的 PCB 放入到就绪队列当中,所以这是由创建态到就绪态转换的一个过程
之后如果一个进程被 CPU 调度,然后它就会从就绪态转换为运行态,这个转换过程我们需要做的就是把进程的运行环境给恢复,并且修改 PCB 当中的内容。就是说把 PCB 当中的那个状态标志位从就绪态改变为运行态,并且把进程的 PCB 从就绪队列当中摘出来。然后这个进程就可以开始被处理运行。
这个地方为什么要恢复进程运行的环境,因为进程之前可能运行到一半,然后被切换了,所以进程的那些运行的中间结果其实是被保存在 PCB 当中的,所以进程当再次被调度的时候,需要把它之前的运行环境给恢复过来。
那么当进程在执行的过程当中,如果说用系统调用的方式,发出了一个等待某个事件的请求,那么我们就需要把这些进程当前运行的环境给保存下来,用于之后进程还可以接着往下执行,并且还需要把进程的 PCB 当中的标志位从运行态改变为阻塞态,然后把进程的 PCB 放到相应的事件的阻塞队列当中,
类似的,如果要从阻塞态转换为就绪态,那么我们需要修改 PCB 的内容,并且把 PCB 从阻塞队列放到就绪队列当中。如果说进程它在这个阻塞队列当中是在等待某种系统资源的分配,那么这个操作系统还需要把这个系统资源分配给进程,
像其他的运行态到就序态的转换,还有运行态到终止态的转换,这些过程其实我都需要修改 PCB 当中的内容,并且有的时候还可能会需要需要回收系统资源或者为进程分配系统资源。
那么可以看到其实进程的状态切换,中间所需要做的事情是比较复杂的,我们需要修改 PCB 的内容,并且把 PCB 修放到相应的正确的队列当中
那么思考一个这样的问题,假如说某一个进程把它的 PCB 从一个队列放到了另一个队列,但是我们并没有把 PCB 当中的状态标志改成相应的新的状态,那么这种情况其实是很危险的,极有可能会导致系统错误,因为 PCB 所处的队列和当前 PCB 当中的状态标志位这两个数据就变得不一致了。
那么为了防止这个问题,就使用了所谓的原语来实现进程控制。原语的特点就是在执行期间不允许被中断,只能一气呵成,这种不可以被中断的操作就可以称之为原子操作。那么像原语其实是采用关中断和开中断两个指令来组合实现的,
当原语相关的这些逻辑代码开始执行之前会先执行一个关中断指令,执行了关中断指令之后,如果说此时有一个外部中断信号进入,那么外部中断信号是被会被忽略的,暂时不会被处理,所以这就保证了原语的这一系列的处理不会被中断。那么只有之后在执行了开中断指令之后,再接收到一个外部中断信号,这个时候才会转入到相应的中断处理程序,然后开始处理。
所以可以看到通过光中段和开中段就可以实现源原语这种一气呵成的操作。也就是刚才我们提到的把 PCB 放到一个队列当中,并且还需要同时保证它 PCB 当中的数据也被修改,这样的事情就可以用原语来实现。那么可以看到原语使用的关中断开中断指令,其实它的权限是非常大的,如果一个用户进程可以随便的使用这两种指令的话,那么就意味着用户进程可以永远不被中断,他会一直霸占着 CPU 资源,这样显然是很危险的事情,所以关中断和开中断指令显然它是一种特权指令,只能在核心态下进行,所以肯定也是运行在核心态的。那么其实原语这个概念,在之前咱们提到操作系统内核小结的时候也提到过,原语它是属于操作系统内核的一部分,它需要运行在核心态
# 进程控制相关的原语
那么操作系统提供了哪些进程控制相关的原语,其实无论哪个原语,要做的无非就是三类事情,首先是更新 PCB 当中的信息,第二是把 PCB 插入到合适的队列当中,第三有可能会涉及到分配或者回收资源这样的事情。另外像更新 PCB 当中的信息会包括比如说像修改进程状态的标志这样的事情,所有的进程控制原语,它都会导致进程的状态改变,所以肯定都会修改进程的状态标志。
另外如果说剥夺了当前正在运行的进程的 CPU 使用权,那么就需要把进程相关的运行环境给保存下来,把它保存到 PCB 当中。如果一个进程它要进入到运行态,那么我们就需要把进程之前的那些运行环境把它给恢复过来
所以其实接下来我们要学习的这些言语无非就是做了这样的三件事情,大家可以用这个为框架来进行理解和记忆。
首先操作系统内核实现了所谓的创建原语,用来实现进程的创建工作,创建原语进行了这样的一系列的操作,大家可以对比刚才提出的这三类事情来进行来进行理解。那么创建原语实现了一个进程,从无到有,从无到创建态,再从创建态进入到就绪队列,进入就绪态这样一个过程,
引起进程创建的事件有这样几种,像用户登录,分时系统当中用户登录成功之后,操作系统会为用户建立一个和他相关的用户管理进程。
那么除此之外,现在多道批处理系统当中,如果说有一个新的作业从外存调入内存要开始运行,那么这个时候操作系统也会为作业建立一个它对应的新的进程。另外有的时候系统用户向操作系统提出某种请求的时候,操作系统会专门新建一个进程来处理用户提出的请求,所以这种情所以如果说一个用户要求操作系统提供服务,也有可能会导致一个进程被创建。另外用户进程也可以主动地申请操作系统,为它创建一个子进程,这就是应用请求导致的进程创建。那么这就是创建原语
另外操作系统还提供了用于实现进程的终止相关工作的撤销原语,撤销原语完成了这样一系列的工作,其实无非也就是更新一些 PCB 的内容,然后回收一些系统资源这样的事情。然后如果说一个处于运行态进程,它运行正常结束,或者说运行的过程中,由于一些程序 bug 导致了异常的结束,比如说像整数除以 0 这样的错误,那么这种情况会使操作系统会使用撤销原语,来使进程从运行态转变为终止态,最后完成了撤销,完成了终止态相关的一系列工作之后,进程就被彻底撤销了。
另外如果一个进程处于就绪态或者阻塞态,那么此时如果有外界干预,比如说像用户主动的请求撤销进程,这个时候操作系统也会使用撤销原语,来使进程直接从用就绪态或者阻塞态直接转变为终止态,然后完成一系列的工作之后,最后把进程彻底的干掉。像外界干预,比如说像我们使用 windows 操作系统,任务管理器来杀进程这样的一种操作,其实就是所谓的外界干预。
第三种,操作系统还提供了进程的阻塞和进程的唤醒,相关的言语就是阻塞原语和唤醒原语,阻塞原语和唤醒原语所做的这一系列的工作,其实也是处理 PCB 的一些内容,或者把它插入到合适的队列这样的一系列的工作。
那么如果一个正在运行的进程,它需要等待系统分配某种资源,或者说需要等待某个事件的发生,操作系统就会使用阻塞原语把进程进行阻塞,从此由此进程会由运行态转变为阻塞态。那么当进程等待的事件发生之后,操作系统又会使用唤醒原语,来把刚才进程从阻塞态给我转变为就绪态。
那么需要注意的是进程的唤醒,这个事件其实就是进程被阻塞的时候所等待的事件,因此阻塞原语和唤醒原语应该是成对使用的,进程因为什么事件被阻塞,那么就应该因为什么事件被唤醒。
另外操作系统还提供了进程切换相关的原语,进程切换相关的原语,其实实现的也是一些 PCB 相关的一系列的操作。那么像当前正在运行的进程时间片到,或者有更高的进程到达,然后抢占了 CPU,或者说当前正在执行的进程主动的申请阻塞,或者说当前进程终止,这些都有可能导致进程的切换。那么这个切换原语会让当前处于运行态的进程变为阻塞态或者就绪态,另外又会让一个处于就绪态的进程进入到运行态,所以这是切换源语的作用。
# 小结
那么我们再来回顾一下小节的内容,首先我们介绍了什么是进程控制,其实进程控制就是要实现进程的各种状态之间的转换,进程控制是用原语来实现的,我们需要注意的是原语是必须一气呵成的,不可中断的一种特殊的程序,而这种一气呵成,不可中断的特性是用开中断和关中断指令来实现的。
之后我们又介绍了进程控制相关的原语,其中阻塞原语和唤醒原语必须要成对的出现,各个原语在背后大概做了哪些事情,大家其实不需要死记硬背,只需要进行理解就可以了。好的,那么这就是小节的全部内容。
- 01
- 中国网络防火长城简史 转载10-12
- 03
- 公告:博客近期 RSS 相关问题10-02