操作系统 进程管理 总结

版权声明:抱最大的希望,为最大的努力,做最坏的打算。 https://blog.csdn.net/qq_37748451/article/details/84348115

第一部分

一、程序的并发执行

1 程序的顺序执行

  我们把一个具有独立功能的程序独占处理机直到最终结束的过程叫做程序的顺序执行。
  程序的顺序执行具有以下特点:
  1. 顺序性
  2. 封闭性
  3. 可再现性

2 多道程序系统中的程序执行环境

  这样的执行环境具有以下3个特点:
  1. 独立性
  2. 随机性
  3. 资源共享性

3 并发执行

两种情况:

第一种:多道程序系统的程序执行环境变化所引起的多道程序的并发执行。
第二种:在某道程序的几个程序段中(例如几个程序)包含着一部分可以同时执行或顺序颠倒执行的代码。

多道程序的并发执行在宏观上是同时进行的,但在微观上仍是顺序执行的。

程序的并发执行可以总结为:一组在逻辑上互相独立的程序或程序段在执行过程中,其执行时间在客观上相互重叠,即一个程序段的执行尚未结束,另一个程序段的执行已经开始的这种执行方式。

注意:程序的并发执行不同与程序的并行执行。程序的并行执行是指一组程序按独立的、异步的速度执行。并行执行不等于时间上的重叠。

1966年Bernstein提出了两个相邻语句可以并发执行的条件:若两个语句没有读写、写写冲突,则两个语句可以并发执行。如果满足Bernstein的3个条件,则认为并发执行不会对程序执行结果的封闭性和可再现性产生影响。

二、进程

由操作系统控制和协调并发程序之间的资源共享和竞争,避免发生预料之外的错误。
我们需要一个能够描述程序的执行过程且能用来共享资源的基本单位,这个基本单位被称为进程(或者任务)。

进程:

  1. 进程是可以并发执行的计算部分。
  2. 进程是一个独立的可以调度的活动。
  3. 进程是一个抽象实体,当它执行某个任务时,将要分配和释放各种资源。
  4. 行为的规则称为程序,程序在处理机上执行时的活动称为进程。
  5. 一个进程是一系列逐一执行的操作,而操作的确切含义则有赖于以何种详尽程度来描述进程。
    可以看到,我们要注重进程是一个动态的执行过程这一概念。我们可以这样定义进程:并发执行的程序在执行过程中分配和管理资源的基本单位。

进程和程序的联系与区别:

  1. 进程是一个动态的概念,而程序则是一个静态概念。
  2. 程序是指令的有序集合,而进程强调执行过程。
  3. 进程具有并发特征(独立性和异步性),而程序没有。
  4. 进程是竞争计算机系统资源的基本单位。
  5. 不同的进程可以包含同一程序,只要该程序多对应的数据集不同。

进程的描述
进程的静态描述由三部分组成:进程控制块(PCB)、有关程序段和该程序段对其进行操作的数据结构集。

PCB
PCB集中反映一个进程的动态特征。进程的PCB是系统感知进程的唯一实体。
创建一个进程时,应首先创建其PCB,然后才能根据PCB中的信息对进程实施有效的管理和控制。当一个进程完成其功能之后,系统则释放PCB,进程也随之消亡。

PCB的内容

  1. 描述信息:(1)进程名或进程标识号;(2)用户名或用户标识号;(3)家族关系。
  2. 控制信息:(1)进程当前状态;(2)进程优先级(包括:占有CPU时间、进程优先级偏移、占据内存时间,等等);(3)程序开始地址;(4)各种计时信息;(5)通信信息。
  3. 资源管理信息:(1)占用内存大小及其管理用数据结构指针;(2)在某些复杂系统中,还有对换或覆盖用的有关信息;(3)共享程序段大小及起始地址;(4)输入输出设备的设备号,索要传送的数据长度、缓冲区地址、缓冲区长度及所用设备的有关数据结构指针等;(5)指向文件系统的指针及有关标识等。
  4. CPU现场保护结构。

进程上下文
进程上下文实际上是进程执行过程中顺序关联的静态描述。进程上下文是一个与进程切换和处理机状态有关的概念。
进程上下文是一个抽象的概念,它包含了每个进程执行过的、执行时的以及待执行的指令和数据,在指令寄存器、堆栈(存放各调用子程序的返回点和参数等)和状态字寄存器等中的内容。

已执行过的进程指令和数据在相关寄存器与堆栈中的内容称为上文,正在执行的指令和数据在寄存器与堆栈中的内容称为正文 ,待执行的指令和数据在寄存器与堆栈中的内容称为下文
进程的系统级上下文又分为静态与动态部分。动态部分是与寄存器上下文相关联的。

进程上下文切换
进程上下文切换发生在不同的进程之间而不是同一个进程内。
进程上下文切换过程一般包含3个部分:(1)保存被切换进程的正文部分(或当前状态)至有关存储区;(2)操作系统进程中有关调度和资源分配程序执行,并选取新的进程;(3)激活被选取的新进程。

进程空间与大小
任一进程,都有一个自己的地址空间,该空间称为进程空间 或 虚空间。进程空间的大小只与处理机的位数有关。例如,16位长处理机的进程空间大小为2^16。程序的执行都在进程空间内进行。用户程序、进程的各种控制表格等都按一定的结构排列在进程空间中。进程空间还被划分为用户空间和系统空间两大部分。用户程序在用户空间内执行,操作系统内核程序在系统空间内执行。(user mode和kernel mode)。
进程的大小就是进程空间的大小。

三、进程状态及其转换

进程状态:

  1. 初始态
  2. 执行状态
  3. 等待状态
  4. 就绪状态
  5. 终止状态

进程状态转换:

四、进程控制

原语:一般地,把系统态下执行的某些具有特定功能的程序段称为原语。原语用来完成进程的创建、撤销以及完成进程各状态间的转换。
原语可分为两类:

  1. 一类是机器指令级的,其特点是执行期间不允许中断,在操作系统中,它是一个不可分割的基本单位(原子性);
  2. 另一类是功能级的,其特点是作为原语的程序段不允许并发执行。

用于进程控制的原语有:创建原语、撤销原语、阻塞原语、唤醒原语。

【创建原语】:
创建进程:系统创建方式(不存在资源继承关系)和父进程创建方式(有资源继承)。
参数:进程名、进程优先级、进程正文段起始地址、资源清单等。

[创建原语流程图]

【撤销原语】:
以下情况导致进程被撤销:

  1. 该进程已完成所要求的功能而正常终止;
  2. 由于某种错误导致非正常终止;
  3. 祖先进程要求撤销某个子进程。

如果被撤销的进程有自己的子进程,则撤销原语先撤销其子进程的PCB结构并释放子进程所占用的资源之后,再撤销当前进程的PCB结构并释放其资源。

[撤销原语流程图]

【阻塞原语】:
进程的执行状态变化到等待状态(一个进程期待某事件的发生,但发生尚不具备条件时),由该进程自己调用阻塞原语来阻塞自己。这里转入进程调度程序是很重要的,避免出现空转而浪费资源。

[阻塞原语流图]

【唤醒原语】:
唤醒一个进程的两种方式:(1)由系统进程唤醒;(2)由事件发生进程唤醒。
唤醒原语既可以被系统进程调用,也可被事件发生进程调用。调用唤醒原语的进程称为唤醒进程

进程状态由 等待状态 -> 就绪状态

 

第二部分

一、进程互斥

由于进程具有独立性和异步性等并发特征,计算机的资源有限,导致了进程之间的资源竞争和共享,也导致了对进程执行过程的制约。

1、临界资源和临界区(临界部分)

临界资源:一次只能供一个进程访问的资源。
临界区:把不允许多个并发进程交叉执行的一段程序称为临界区(critical region)或临界部分(critical section)。

临界区是由属于不同并发进程的程序段共享公用数据或公用数据变量而引起的,临界区不可能用增加硬件的方法来解决。因此,临界区也可以被称为访问公用数据的那段程序。

当一个进程使用该临界资源时,其他需要访问该资源的进程必须阻塞,直到占用者释放该资源。

2、间接制约

把这种由于共享某一公有资源而引起的在临界区内不允许并发进程交叉执行的现象,称为由共享公有资源而造成的对并发进程执行速度的间接制约。这里的“间接”二字主要是指各并发进程的速度受公有资源的制约,而非进程之间的直接制约。

3、互斥

互斥:一组并发进程中的一个或多个程序段,因共享某一公有资源而导致它们必须以一个不允许交叉执行的单位执行。也就是说,不允许两个以上的共享该资源的并发进程同时进入临界区。

一般情况下,作为程序段的一个过程不允许多个进程同时访问它。但如果该过程是纯过程,则各并发进程可以同时访问它。纯过程是指在执行过程中不改变过程自身代码的一类过程。

一组并发进程互斥执行时必须满足如下准则:

  1. 平等竞争:不能假设各并发进程的相对执行速度。即各并发进程享有平等地、独立地竞争共有资源的权利,且在不采取任何措施的条件下,在临界区内任意指令结束时,其他并发进程可以进入临界区。
  2. 不可独占:并发进程中的某个进程不在临界区时,它不能阻止其他进程进入临界区。
  3. 互斥使用:并发进程中的若干个进程申请进入临界区时,只能允许一个进程进入。
  4. 有限等待:并发进程中的某个进程从申请进入临界区时开始,应在有限时间内得以进入临界区。

二、互斥的实现

1、互斥的加锁实现

对临界区加锁以实现互斥。当某个进程进入临界区后,它将锁上临界区,直到它退出临界区为止。并发进程在申请进入临界区时,首先测试该临界区是否上锁。

加锁实现中的lock(key[S])和unlock(key[S])均为原子操作。有一点需要注意的是:在系统实现时锁定位key[S]总是设置在公有资源所对应的数据结构中的。

加锁实现的缺点:

  1. 循环测试锁定位将损耗较多的CPU计算时间。
  2. 另外使用加锁法实现进程间互斥时,还将导致在某些情况下出现不公平的情况。例如进程PA和PB:
    进程PA:
A:
lock(key[S])
<S>
unlock(key[S])
Goto A

进程PB:

B:
lock(key[S])
<S>
unlock(key[S])
Goto B

由于两个进程中均有Goto语句(Goto A和Goto B),这就有可能出现其中一个进程的执行,导致另一个进程长期得不到处理机资源,而处于永久饥饿状态(starvation)

分析可以知道,一个进程能否进入临界区取决于进程自己调用lock过程去测试相应的锁定位。也就是说,每个进程能否进入临界区是依靠进程自己的测试判断。这样,没有获得执行机会的进程当然无法判断,从而出现不公平现象。

那么是否有办法解决这个问题呢?当然,很明显,办法是有的,我们可以为临界区设置一个管理员,由这个管理员来管理相应临界区的公有资源,它代表可用资源的实体,这个管理员就是信号量

2、信号量和P、V原语

信号量和P、V原语是荷兰科学家E. W. Dijkstra提出来的。

【信号量】 在操作系统中,信号量sem是一个整数

  • sem >= 0时,代表可供并发进程使用的资源实体数;
  • sem < 0时,表示正在等待使用临界区的进程数。

显然,用于互斥的信号量sem的初值应该大于0,而建立一个信号量必须说明所建信号量代表的意义,赋初值,以及建立相应的数据结构,以便指向那些等待使用该临界区的进程。

【P、V原语】
信号量的数值仅能由P、V原语操作改变。采用P、V原语,可以把类名为S的临界区描述为:When S do P(sem) 临界区 V(sem) od。

  • 一次P原语操作使信号量sem减1
  • 一次V原语操作使信号量sem加1

P原语操作:

  1. sem减1;
  2. 若sem减1后仍大于或等于0,则P原语返回,该进程继续执行;
  3. 若sem减1后小于0,则该进程被阻塞后进入与该信号相对应的队列中,然后转进程调度。

V原语操作:

  1. sem加1;
  2. 若相加结果大于0,V原语停止执行,该进程返回调用处,继续执行;
  3. 若相加结果小于或等于0,则从该信号的等待队列中唤醒一个等待进程,然后再返回原进程继续执行或转进程调度。

    注意:P、V原语操作(必须以原语实现)都是原子操作,且在P、V原语执行期间不允许中断发生。

这里给出一个使用加锁法的软件实现方法来实现P、V原语:

P(sem):
    begin
        封锁中断;
        lock(lockbit)
        val[sem]=val[sem]-1
        if val[sem]<0
            保护当前进程CPU现场
            当前进程状态置为“等待”
            将当前进程插入信号sem等待队列
            转进程调度
        fi
        unlock(lockbit);开放中断
    end
V(sem):
    begin
        封锁中断;
        lock(lockbit)
        val[sem]=val[sem]+1
        if val[sem]<=0
            local k
            从sem等待队列中选取一个等待进程,将其指针置入k中
            将k插入就绪队列
            进程状态置位“就绪”
        fi
        unlock(lockbit);开放中断
    end

3、用P、V原语实现进程互斥

设信号量sem是用于互斥的信号量,且其初始值为1表示没有并发进程使用该临界区。显然,由前面论述可知,只要把临界区置于P(sem)和V(sem)之间,即可实现进程之间的互斥。

用信号量实现两个并发进程PA和PB互斥的描述如下:
(1)设sem为互斥信号量,其取值范围为(1,0,-1)。其中sem=1表示进程PA和PB都未进入类名为S的临界区,sem=0表示进程PA或PB已进入类名为S的临界区,sem=-1表示进程PA和PB中,一个进程已进入临界区,而另一个进程等待进入该临界区。
(2)实现过程:

Pa:
    P(sem)
    <S>
    V(sem)
    .
    .
    .
Pb:
    P(sem)
    <S>
    V(sem)
    .
    .
    .

三、进程同步

【进程间的直接制约】:一组在异步环境下的并发进程,各自的执行结果互为对方的执行条件,从而限制各进程的执行速度的过程称为并发进程间的直接制约。这里的异步环境主要是指各并发进程的执行起始时间的随机性和执行速度的独立性。

【进程间的同步】:把异步环境下的一组并发进程因直接制约而互相发送消息而进行互相合作、互相等待,使得各进程按一定的速度执行的过程称为进程间的同步。
具有同步关系的一组并发进程称为合作进程,合作进程间相互发送的信号称为消息或事件。

用消息实现进程同步:

wait(消息名)
表示进程等待合作进程发来的消息。

用
signal(消息名)
表示向合作进程发送消息。

过程wait的功能是等待到消息名为true的进程继续执行,而signal的功能则是向合作进程发送合作进程所需要的消息名,并将其值置为true

【进程互斥和进程同步】:进程同步不同于进程互斥,进程互斥时它们的执行顺序可以是任意的。一般来说,也可以把个进程之间发送的消息作为信号量看待。与进程互斥时不同的是,这里的信号量只与制约进程及被制约进程有关,而不是与整租并发进程有关。因此,称该信号量为私用信号量(private semaphore)。一个进程Pi的私用信号量semi是从制约进程发送来的进程Pi的执行条件所需要的信息。与私用信号量相对应,称互斥时使用的信号量为公用信号量

【用P、V原语实现进程同步】
首先为各并发进程设置私用信号量,然后为私用信号量赋初值,最后利用P、V原语和私用信号量规定各进程的执行顺序。

四、生产者-消费者问题

把并发进程的同步和互斥问题一般化,可以得到一个抽象的一般模型,即生产者-消费者问题(producer-consumer problems)
把系统中使用某一类资源的进程称为该资源的消费者,而把释放同类资源的进程称为该资源的生产者

设生产者进程和消费者进程是互相等效的,其中,各生产者进程使用的过程deposit(data)和各消费者使用的进程remove(data)可描述如下:
首先,可以看到,上述生产者-消费者问题是一个同步问题。即生产者和消费者之间满足如下条件:

  • (1)消费者想接收数据时,有界缓冲区至少有一个单元是满的。
  • (2)生产者想发送数据时,有界缓冲区至少有一个单元是空的。

另外,由于有界缓冲区是临界资源,因此,各生产者进程和各消费者进程之间必须互斥执行

设公用信号量mutex保证生产者进程和消费者进程之间的互斥,设信号量avail为生产者进程的私用信号量,信号量full为消费者进程的私用信号量。信号量avail表示有界缓冲区中的空单元数,初值为n;信号量full表示有界缓冲区中非空单元数,初始值为0。信号量mutex表示可用有界缓冲区的个数,初始值为1。

deposit(data):
    begin
        P(avail)  // 检查是否有空单元可以使用
        P(mutex)  // 检查临界区是否被占用
        送数据入缓冲区某单元
        V(full)
        V(mutex)
    end
remove(data):
    begin
        P(full)  // 检查是否有非空单元
        P(mutex)  // 检查临界区
        取缓冲区中某单元数据
        V(avail)
        V(mutex)
    end

在这个例子中,由于包含多个公用信号量和私用信号量,因此P、V原语的操作顺序需要非常小心。一般来说,由于V原语是释放资源,所以可以以任意次序出现。但P原语则不然,如果次序混乱,将会造成进程之间的死锁。例如:如果我们调换P(full)和P(mutex),便有可能导致程序一直占用临界区,而无法得到资源(如果此时full=0,mutex >= 0,程序进入临界区后得不到资源,但又无法释放临界区),从而导致死锁。

第三部分

一、死锁的概念

1、死锁定义

【死锁】是指各并发进程互相等待对方所拥有的资源,且这些并发进程在得到对方的资源之前不会释放自己所拥有的资源(排除管理干预)。从而造成大家都想得到资源而又都得不到资源,各并发进程不能继续向前推进的状态。(如下图)

一般地,可以把死锁描述为:有并发进程P1,P2,……,Pn,它们共享资源R1,R2,……,Rm(n>0, m>0, n>=m)。其中,每个Pi(1<=i<=n)拥有资源Rj(1<=j<=m),直到不再有剩余资源。同时,各Pi在又不释放Rj的前提下要求得到Rk(k不等于j,1<=k<=m),从而造成资源的互相占用和互相等待。在没有外力的驱动的情况下,该组并发进程停止往前推进,陷入永久等待状态。

2、死锁的起因

死锁的起因是并发进程的资源竞争,而计算机的资源又是有限的,不可能无限制的给每个进程提供资源。

3、产生死锁的四个必要条件

  1. 互斥条件。并发进程所要求和占有的资源是不能同时被两个以上的进程使用或操作的,进程对它所需要的资源进行排他性控制。
  2. 不可剥夺条件。进程所获得的资源在未使用完毕之前,不能被其他进程强行剥夺,而只能有获得该资源的进程自己释放。
  3. 部分分配。进程每次申请它所需要的一部分资源,在等待新资源的同时,继续占用已分配到的资源。
  4. 环路条件。存在一种进程循环链,链中每一个进程已获得的资源同时被下一个进程所请求。

死锁破除:只要上述四个条件中的任意一个条件被破坏,死锁即可破除。

二、死锁的消除方法

解决死锁的方法一般可分为预防、避免、检测与恢复3种。

1、死锁预防

预防是采用某种策略限制并发进程对资源的请求。(静态策略)
(1)打破资源的互斥和不可剥夺这两个条件。例如允许进程同时访问某些资源。(缺点?)
(2)打破资源的部分分配这个死锁产生的必要条件。即预先分配各并发进程所需要的全部资源。如果某个进程的资源得不到满足的时候,则安排一定的等待次序让其他进程释放资源。(缺点?)
(3)打破死锁的环路条件。即把资源按顺序排列,使进程在申请、保持资源时不形成环路。如有m种资源,则列出R1< R2 < …… < Rm。若进程Pi保持了资源Ri,则它只能申请比Ri级别更高的资源Rj(Ri < Rj)。释放资源时必须是Rj先于Ri被释放,从而避免环路的产生。这中方法的缺点是限制了进程对资源的请求,而且对资源的分类编序也耗去一定的系统开销。

2、死锁避免(动态预防)

在系统动态分配资源的过程中预测出死锁发生的可能性并加以避免。
一种基本模式是把进程分为多个步,其中每个步所使用的资源是固定的,且在一个步内,进程所保持的资源数不变。即进程的资源请求、使用与释放要依靠不同的步完成。
死锁避免需要占据较大的系统开销。

3、死锁检测和恢复

当进程进行资源请求时,死锁检测算法检查并发进程组是否构成资源的请求和保持环路。(有限状态转移图、PetriNet等技术都可有效的判断死锁发生)。死锁的恢复办法较多,最简单的是终止各锁住的进程,或按一定的顺序中止进程序列,直至已释放的资源足够剩下的进程执行结束为止。另外,也可从被锁住的进程强行剥夺资源打破不可剥夺条件解除死锁。

猜你喜欢

转载自blog.csdn.net/qq_37748451/article/details/84348115