[2.1.3]进程管理——进程控制
创始人
2024-05-30 00:17:14

文章目录

  • 第二章 进程管理
    • 进程控制
      • (一)什么是进程控制
      • (二)如何实现进程控制
        • 如何实现原语的“原子性”?
      • (三)进程控制相关的原语
        • (1)进程的创建——创建原语
        • (2)进程的终止——撤销原语
        • (3)进程的阻塞和唤醒——阻塞原语、唤醒原语
        • (4)进程的切换——切换原语
    • 小结

第二章 进程管理

进程控制

进程控制

  • 基本概念

    • 什么是进程控制?

    • 如何实现进程控制?

      用“原语”实现。

    • 进程控制相关的原语

      • 进程的创建
      • 进程的终止
      • 进程的阻塞
      • 进程的唤醒
      • 进程的切换

(一)什么是进程控制

  进程控制的主要功能是对系统中的所有进程实施有效的管理,它具有创建新进程、撤销已有进程、实现进程状态转换等功能。

  简单来说,进程控制,就是要实现进程的状态转换。

  比如“创建新进程”,不就是让进程由“创建态”转换为“就绪态”吗。“撤销已有进程”,就是让进程由“运行态”转换为“终止态”。

  那么,在进程状态转换的过程中,操作系统需要做一些什么事情呢?——这就是这个小节我们要讨论的内容。

(二)如何实现进程控制

  进程控制是要用“原语”实现的。

  而“原语”的概念,我们在第一章当中提到过。——操作系统的内核中,有一种特殊的程序叫原语,它的执行具有原子性。也就是说,这段程序的运行必须一气呵成,中间不允许被中断。

  也就是说,进程控制(实现进程的状态转换)的操作一定是一气呵成的。

  思考:为什么进程控制(状态转换)的过程要“一气呵成”?

  例如:假设PCB中的变量state表示进程当前所处状态,1表示就绪态,2表示阻塞态……

image-20230306204937335

  那么,如果一个进程是处于就绪态的(state=1),这个进程的PCB肯定是要挂在就绪队列里的。而如果state=2的话,这个进程的PCB就一定挂在阻塞队列里。

  接下来,考虑这样一种情况:

  处于阻塞队列里的进程,它肯定是在等待某一事件的发生。那假设PCB2这个进程,它所等待的事件已经发生了,那么,此时这个进程就要从阻塞态→就绪态了。

  所以,操作系统内核程序就需要把这个进程的状态从阻塞态变为就绪态,而进行状态转换的过程,至少需要做两件事情:①把PCB2state设为1;②把PCB2从阻塞队列放到就绪队列。

  接下来,考虑这样一种情况:

  假设我把PCB2的state已经设为1了(如上述的步骤①),而此时,(在执行步骤②,也就是将其从阻塞队列放到就绪队列之前)收到了中断信号,系统就会转而去处理中断。就会导致这样一个结果,PCB2的state=1,但是它却处在阻塞队列里。就会导致,该进程的state所表示的状态,和该进程所处的队列不统一。

image-20230306205257495

  因此,如果操作系统对进程的状态转换如果不能“一气呵成”。就有可能导致操作系统中的某些关键数据结构信息不统一的情况,这会影响操作系统进行后续的别的一些工作,会让系统出错。

  那刚好,“原语”这种程序,它具有一气呵成、不可中断的性质,所以我们可以用“原语”这种特殊的程序来实现“一气呵成”这样的事情,从而来实现进程控制。

如何实现原语的“原子性”?

  原语的执行具有原子性,即执行过程只能一气呵成,期间不允许被中断

  现在会有个疑问,为什么“原语”就“一气呵成、不可中断”了呢?

  其实它的原子性,是由两个特权指令:“关中断指令”和“开中断指令”实现的。

  我们来看一下关中断、开中断,这两个指令的作用。

image-20230306210033197

  假设这是一个正在运行的内核程序,那CPU会依次执行这些指令,而且根据第一章的讲解,我们知道,CPU每执行完一条指令,之后,都会例行检查是否有中断信号需要处理。

  如果它在执行完指令2之后,CPU发现有一个中断信号,那么在这种情况下,CPU就会暂停当前执行的程序,转而执行处理中断的程序。等这个中断处理程序完成之后,再回到原来的程序中继续往下执行。

image-20230306210259584

  正常情况:CPU每执行完一条指令都会例行检查是否有中断信号需要处理,如果有,则暂停运行当前这段程序,转而执行相应的中断处理程序。

  接下来看一下,如果执行到了“关中断指令”,会出现什么情况。

  CPU在依次执行这些指令,当它执行了“关中断指令”这条特权指令之后,CPU就不再例行检查中断信号了。

  CPU会接着往下执行。那如果在执行指令a后,有一个外部中断信号到来了,它就并不会像之前一样例行检查是否有中断信号,而是会继续往下执行,一直到CPU执行了“开中断指令”之后,它才会恢复以前的那种习惯,即“每执行完一条指令,检查一下此时是否有中断信号”。

image-20230306210724263

  CPU执行了关中断指令之后,就不再例行检查中断信号,直到执行开中断指令之后才会恢复检查。

  开中断指令执行之后,它这时才会检查是否有中断信号,于是便发现:来了一个外部中断信号我还没有处理。然后转而执行这个中断处理程序。

image-20230306210903711

  从这个例子我们就可以看到,在关中断和开中断这两个指令之间的这一系列的指令序列,它们的执行肯定是不可被中断的,这样就实现了所谓的“原子性”。

  这样,开中断、关中断 之间的这些指令序列就是不可被中断的,这就实现了“原子性”。


  这两个指令是特权指令。

  但是,我们思考一下:如果这两个特权指令允许普通的用户程序使用的话,会发生什么情况?

  那这是不是就意味着:我可以直接在我的程序最开头,植入一个“关中断指令”,一直到我的程序末尾,再执行“开中断指令”,这样的话,只要我的程序上CPU运行了,那我的程序就会一直霸占着CPU,而不会被中断。那显然,这种情形是不允许发生的。

  所以,开中断、关中断指令是特权指令,只能让内核使用,而不能让普通用户使用。


  至此,再次总结一下:

  1、进程控制(进程的状态转换)这个事情,必须一气呵成。而想要做到一气呵成,我们可以用“原语”这种特殊的程序来实现。

  2、而“原语”的实现,需要由开中断指令和关中断指令来配合着完成。


  接下来需要探讨的是,实现进程控制的这些“原语”,到底做了哪些事情?

(三)进程控制相关的原语

  这些原语,每个原语所做的事情具体有哪些,的确很多,但不需要死记硬背,理解其前因后果即可。以理解为主,而不是想着把每一个步骤刻意的默写到位。

(1)进程的创建——创建原语

  首先来看用于实现“进程的创建”的原语。

  如果操作系统要创建一个进程,那么它就必须使用创建原语

  而创建原语,会干这样几件事情:

  • 首先,申请一个空白的PCB。因为PCB是进程存在的唯一标志,所以,要想创建一个进程肯定要创建一个和它相对应的PCB。

  • 另外,还会给这个进程分配它所需要的资源。比如内存空间,等等。

  • 然后还会把这个PCB的内容进行一番初始化。比如分配PID、设置UID,等等。

  • 最后,它还会把这个PCB插入到就绪队列。

    所以,创建原语让一个进程从创建态→就绪态。


  那有一些典型的事件,会引起操作系统使用创建原语创建一个进程。

  • 比如,当一个用户登录的时候。操作系统会给这个用户建立一个与之对应的用户管理进程,或者用户通信进程,等等。

  • 或者,发生作业调度的时候,也会创建一个进程。

      作业,就是此时还放在外存里的、还没有投入运行的程序。所谓的作业调度就是指,从外存当中挑选一个程序,把它放入内存,让它开始运行。

      那我们知道,当一个程序要运行的时候,肯定是要创建一个进程的。所以,当发生作业调度的时候,就需要使用到创建原语了。

  • 有时,一个进程可能向操作系统提出某些请求,操作系统会专门建立一个进程来处理这些请求。

  • 还有的时候,一个进程可以主动请求创建一个子进程。


  总之,发生这些事件的时候,都会引起系统创建一个新的进程,也就是说,它会使用到创建原语。

image-20230306212524354

(2)进程的终止——撤销原语

  撤销原语是终止一个进程所使用的。

  使用撤销原语之后,就能使进程由某种状态转向终止态,最终这个进程从系统中彻底消失。

  撤销原语需要做这样的一些事情:

  • 首先,既然要撤销一个进程,那肯定需要找到这个进程相应的PCB。
  • 如果这个进程此时正在运行的话,那就需要立即剥夺它的CPU使用权,然后把CPU分配给其他进程。
  • 同时,操作系统在杀死一个进程的时候,还会杀死它的所有子进程。
  • 并且,这个进程被撤销之后,它之前所占有的那些资源应该归还给它的父进程。
  • 最后的最后,还需要把这个进程的PC B从系统中删除。

  很多事件会引起一个进程的终止:

  • 比如,一个进程自己请求终止(用了exit系统调用)。
  • 另外,如果一个进程做了一些非法的事件,比如整数除以0、非法使用特权指令,这种情况也会被操作系统强行撤销。
  • 外界干预。比如在使用Windows电脑的时候出现卡死的情况,我们会用Ctrl+Alt+delete打开任务管理器来强行结束某一进程。

image-20230306215800242

(3)进程的阻塞和唤醒——阻塞原语、唤醒原语

  有时一个进程要从运行态→阻塞态,这时操作系统就会在背后执行一个阻塞原语来实现。

  阻塞一个进程比较简单:

  • 首先,找到要阻塞的进程,它对应的PCB。

  • 之后,需要保护进程运行的现场,系统还需要将PCB的状态信息设置为“阻塞态”,还要让进程下处理机、暂停其运行。

    什么叫“保护进程运行现场”,这个一会儿再解释,因为这又是一个比较庞大的话题。

  • 最后,将PCB插入相应事件的等待队列。


  经过之前的学习我们知道,一个进程需要被阻塞,那肯定是因为它主动请求要等待某一事件的发生。

  而如果这个进程所等待的事件发生了之后,这个进程就会被唤醒,也就是说,操作系统会让这个进程的状态从阻塞态→就绪态。

  那么这个时候就要用到唤醒原语。

  唤醒原语需要做这样几个事情:

  • 首先,要找到它的PCB。
  • 然后,把PCB从等待队列里面移除,并把它的状态信息设置为就绪态。
  • 并且把PCB插入到就绪队列。

  无论是阻塞原语、唤醒原语,它们做的这个流程其实很容易理解。

  但是需要注意的是:一个进程因为什么事情被阻塞,就应该被什么事情给唤醒。所以,唤醒原语和阻塞原语,必须是成对使用的。

image-20230306221911994

(4)进程的切换——切换原语

  切换原语,会让此时正处于运行态的进程下处理机,让它回到就绪队列;并且从就绪队列当中,选择一个处于就绪态的进程,让它上处理机运行。

  所以,切换原语会让两个进程的状态发生改变:一个是运行态→就绪态;另一个是就绪态→运行态。

  切换原语需要做如下一些事情:

  • 首先,要把进程的运行环境信息存到PCB当中

    什么叫“进程的运行环境信息”呢?这点涉及到一些硬件的知识,我们一会儿再展开细聊。

  • 另外,它还会把进程的PCB移到相应的队列。

  • 它还会挑选一个进程,让它上处理机运行,并且更新其PCB。

  • 同时,它还会根据这个新进程的PCB,恢复出它所需要的运行环境。

  什么叫“保存运行环境”,什么叫“恢复运行环境”,这是比较难理解的地方,接下来我们深入探讨一下这个问题。

再次拓展:程序是如何运行的?

image-20230306222533296

  通过之前的学习,我们已经了解到了,一个程序的运行需要经历这样一个流程。

  程序运行之前,需要把它的指令放到内存当中,然后CPU从内存中读取这些一条一条的指令并且执行。

  但是接下来我们要拓展一个更深层次的细节:

  CPU在执行这些指令的过程中,需要进行一系列的运算。那么,CPU当中会设置很多的“寄存器”来存放这些指令在运行过程当中所需要的某些数据。总之,寄存器,就是CPU里面用于存放数据的一些地方。


  那CPU里面会有各种各样的寄存器。

  比如说,我们之前提到过的PSW,就是程序状态字寄存器,CPU的状态,内核态/用户态,这个状态信息,就是保存在PSW这个寄存器里面的(当然,PSW里面还保存了一些其他的信息,这个我们就不说了,这是计组需要探讨的内容)。

  另外,CPU中还会有一个比较关键的寄存器,叫做PC,也就是程序计数器寄存器,这个寄存器里面存放的是接下来需要执行的指令它的地址是多少。

  另外,CPU中还会有一个指令寄存器IR。这个寄存器中存放的是,当前CPU正在执行的那条指令。

  此外,CPU还会有其他的一些通用寄存器,用来存放一些别的重要信息。

  总之,CPU中有很多寄存器,我们这只列举了操作系统这门课需要了解一下的寄存器。

image-20230306223407329


  接下来我们分析一下,对于如下这样一系列指令的执行,在背后发生了什么样的事情?

image-20230306223421065

  • 如果当前CPU执行的是指令1,那么它会把指令1的内容读到IR当中,并且,PC中会存放接下来它应该执行的那条指令,也就是指令2的地址。
    • 此外,在执行了指令1时,它发现,它要做的是在内存中的某个地方,写入变量x的值。那么CPU在执行指令1的时候,就会往内存中的某个地方写入变量x的值,为1。

image-20230306223757035

  • 执行完指令1后,CPU就会执行下一条指令,那么通过PC这个寄存器,它就知道下一条要执行的指令,应该是指令2,所以接下来它会取出指令2,把指令2的内容放在IR中。同时,PC的内容也更新为再下一条指令。
    • 那么,指令2的内容是,把变量x的值放到某一个通用寄存器当中。所以,CPU会从内存中取出这个x变量的值,把它放到通用寄存器当中。于是这个通用寄存器的内容就变成了1。

image-20230306224104334

  • 接下来,CPU又要执行再下一条指令。同理,它会取出指令3,然后PCIR的内容同样也会更新。
    • 对于指令3的内容,它会把通用寄存器中的数据进行+1的操作。所以,通用寄存器中的值就会从1变成2。
  • 再接下来,CPU又会执行再下一条指令。
    • 此时,执行的这条指令4,是让它把这个通用寄存器当中的内容,把它重新写回到变量x所存放的位置当中。所以执行了指令4之后,就会把内存中x的值,从1改为2。

image-20230306224411217

  可以看到,我们的int x=1;x++;两个操作,其实CPU是在背后通过执行更基本的指令,来完成的。

  并且从刚才讲的这些过程当中我们可以发现,这些指令按顺序执行的过程当中,有很多中间结果是放在这些寄存器当中的。比如x++;这个操作,刚开始得出的2这个值并没有赋给x,而是先放在了通用寄存器当中。

  更值得注意的是,这些寄存器,并不是当前正在执行的这个进程所独属的。如果其他进程再上CPU运行的话,那么这些寄存器也会被其他进程所使用。

  那么,这就会发生一种情况:

  还是刚才的例子,假设CPU执行完指令3之后,此时CPU需要转而执行另一个程序的话。

image-20230306224837680

  我们知道,另一个进程如果上CPU运行的话,另一个进程也会同样地使用到这些寄存器。所以,另一个进程上CPU运行的时候,有可能把前一个进程在寄存器当中保留的这些中间结果给覆盖掉。

image-20230306225014057

  而我们刚才的那个进程不是执行到了指令3吗,而因为刚才执行到指令3时,寄存器当中得到的中间结果,此时都已经被覆盖掉了,所以这个进程就已经没有办法再往下运行了。

  所以,为了解决这个问题,可以采取这样的策略:

  当一个进程,它要下处理机的时候,可以把它之前运行的这个运行环境的信息,把它保存在自己的PCB当中。当然,这个PCB当中并不需要把所有的寄存器信息都保存下来,只需要保存一些必要的信息就可以了(比如PSW、PC、通用寄存器)。

image-20230306225356421

  比如,这个进程在执行指令3后,要下处理机了,那么我们将此时必要的寄存器信息保存在其PCB当中,接下来才去切换成别的进程。

  接下来,别的进程在使用CPU的时候,可能会往这些寄存器里面写各种各样的数据。总之,会覆盖之前那个进程的数据。

image-20230306225554428

  但是,当之前的那个进程需要重新回到CPU运行的时候,操作系统就可以根据之前保存下来的这些信息,来恢复它的运行环境了。那把它的运行环境恢复之后,CPU就知道,接下来它要执行的是指令4,并且此时通用寄存器当中存放的数据是2。

image-20230306225812294

  所以,既然接下来要执行的是指令4。那CPU就会根据PC的指向,把指令4的指令内容取到IR当中,同时再让PC去指向下一条指令。然后执行当前要执行的指令4,看看该指令具体要干什么,它发现,它需要把当前通用寄存器当中的内容,写回到x存放的位置。

image-20230306230032532

  所以,接下来,它就会把2这个数据,写回到x的这个位置。

image-20230306230144147

  至此,这两个C语言代码就真正完成了。

  上述讲了这么多的内容,主要就是为了让大家理解,什么叫“进程的运行环境信息”。其实所谓的“进程运行环境”,或者叫“进程上下文(Context)”,它就是运行过程当中,寄存器中存储的那些中间结果。当一个进程需要下处理机的时候,需要把它的运行环境存储到自己的PCB当中;而当一个进程需要重新回到CPU运行的时候,就可以重新从PCB当中恢复它之前运行的那个环境,让它继续往下执行了。

  所以,保存进程的运行环境、恢复进程的运行环境,这是实现进程并发运行的一个很关键的技术。


image-20230306230520024

小结

image-20230306230558270

(这些硬件的知识,在学过计组后会更好理解了)

  对于相关原语具体做了哪些步骤,不需要死记硬背,理解即可。其实,无论是哪种原语,它所做的工作,无非就是三类事情:

  1、更新PCB当中的一些信息(主要是:①修改进程状态字state;②保存/恢复运行环境)

  2、把PCB插入到某合适的队列当中

  3、在进程创建、终止的过程中,还应考虑分配/回收资源的问题

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...