进程管理(以Unix系统为例)

1)进程模型

1.1 程序和进程的区别

  • 程序是便编写好的指令(代码)
  • 进程是程序的一次执行活动,活动有生命周期,运行过程中需要处理数据

1.2 进程的运行方式

  • 真并行:多个CPU或者CPU多核
  • 伪并行:一个CPU的时间分成多个较小的时间片,轮流分配给多个任务运行。

1.3 进程的管理

用程序控制块(PCB\PTE)管理进程的信息

在这里插入图片描述

进程=程序+数据+进程控制块

  • 程序控制块

    存放进程的管理和控制信息的数据结构。它是进程管理和控制的最重要的数据结构,每一个进程均有一个PCB,在创建进程时,建立PCB,伴随进程运行的全过程,直到进程撤消而撤消。

  • 对于程序和进程关系的理解

    例如:同时打开很多word,word是一个程序,不同的窗口是不同的进程。

2)进程之间的关系

  • 在unix中,每个进程有且只有一个父进程所有进程都由一个祖先进程创造而来,祖先进程没有父进程

  • unix启动时会创造一个进程(init),工作到机器关机

  • 父进程管理子进程:父进程创建子进程,子进程结束时候需要父进程帮忙清理僵尸态,释放掉占用的资源。

  • 父进程结束时,如果还有正在运行的子进程,父进程会有以下两种做法:

    1. 杀死子进程
    2. 将子进程的父进程设置为init
  • 系统调用fork创造进程

3)进程的状态

  • 正在运行(Running):进程获得了所需要的所有资源,并且得到了CPU正在运行

  • 就绪状态(Ready):进程准备好了相关的资源,由于CPU正在为其他进程服务,在等待CPU。

  • 阻塞状态(Block):还有其他资源没有准备好。

在这里插入图片描述

  1. 正在运行的进程发现缺少相关资源,主动去睡觉
  2. 调度器分配给进程的时间片用完
  3. 调度器分配给进程时间片
  4. 已经准备好被占用的相关的资源,被资源占用者叫醒
  • Running和Ready 合成为 Runnable,可运行态,表示从众多进程中选择一个执行,执行的即为Running,其他未执行的称为Ready

  • 进程刚被创建时候的状态,需要等待分配最基本的资源

  • 进程结束时,转入僵尸态,需要父进程帮忙释放掉自己占用的资源

4)线程

4.1 线程模型

目的:进程中需要同时执行多个任务序列,多个执行的任务需要共享数据

  • 进程中每个用户对应一个执行序列,这个执行序列就是线程;线程是进程的多个任务,里面包含自己的线程描述符,基本的数据,可以被独立的调度,独立的运行

  • 调度的最小单元是线程

  • 资源分配的最小单位是进程

4.2 线程的实现

实现的方式:

  1. 内核管理进程,进程内部维护运行时,里面维护自己的线程表。操作系统分配时间片给进程进程分配时间片给线程

    优点:老旧的操作系统中,操作系统不支持线程;每个进程内部可以采用不同的线程调度策略,使得调度策略个性化

    缺点:当进程中的某个线程缺少资源时,会向进程反应,进程通知内核之后,被设置为阻塞态(Blocked),会导致进程中其他不需要该资源的线程被阻塞

  2. 操作系统内核直接维护进程和线程表

    优点:不会因某个线程的资源占用影响使得其他线程被阻塞

    缺点:老旧系统不支持,需要改造;不支持个性化调度策略

  3. 把一个进程中的线程分成多组,每一组由不同的线程管理,操作系统管理主线程

弹出式线程:用完不进入阻塞态,直接丢弃,用时创建新的。

多线程会有可能造成资源冲突

5)调度算法

5.1 调度算法的目标

  • 进程的调度:Running和Ready中来回转换

  • 进程分类:CPU密集型、I/O密集型

    CPU密集型:大量占用CPU进行计算

    I/O密集型:涉及到数据输入输出

  • 目标:公平、平衡

    公平:每个进程的到时间片

    平衡:各个进程得到的时间相对平均

  • 对于不同类型操作系统的目标:

    大型操作系统:较大的吞吐量(单位时间内完成任务数量)和较短的平均周转时间(任务完成时间)

    交互式系统:足够短的相应时间,保证各个进程在人的接受范围内做出相应

    实时系统:根据用户需要调度、稳定、达到设定的目标

5.2 调度算法的实现

5.2.1 批处理系统的调度
  • 先来先服务(First Come First Served):短任务等待时间较长,系统效率不高

  • 最短作业优先(Shortest Job First ):可能造成长作业的饥饿(长时间得不到执行)

  • 最短剩余时间优先(Shortest Remaining-time Next ):允许暂停任务,预期算出剩余时间

  • 高响应比优先(High Response-ratio First):

    周转时间 = 任务到达时间-任务结束时间 (周转时间 = 等待时间+执行时间)

    相应比(加权周转时间)= 周转时间/执行时间 = 1+等待时间/执行时间

5.2.2 交互式系统的调度
  • 轮转调度(Round-robin scheduling ):多个任务轮流使用CPU,达到伪并行的效果

  • 优先级调度(Priority scheduling ):按照优先级轮转调度,优先级

    任务的优先级划分为0~127,其中0最高

    实时进程优先级:0~39(任务必须马上运行,时间上得到保证,不能耽误、很重要的进程)

    普通进程优先级= base(固定40) + nice(静态优先) + cpu_penalty (动态优先)

    nice:(0~39),默认20,用户只可以调大nice,root可以随意调整nice值

    cpu_penalty:占用CPU时间越长,惩罚值越大,每秒钟惩罚值减半(防止最后优先级都变为127,减半参数为0.5,参数可调)

  • 其他:多级队列(Multiple queues )、最短进程优先(Shortest process next )、保证调度(Shortest process next )、彩票调度(Lottery scheduling )、公平分享调度(Fair-share scheduling)

6)竞争

  • 互斥:两个线程抢占同一资源产生竞争,导致冲突。这样的资源叫关键资源(临界资源)
    关于临界资源的约束

    1. 如果有若干进程要求进入空闲的临界区,一次仅允许一个进程进入。
    2. 任何时候,处于临界区内的进程不可多于一个。如已有进程进入自己的临界区,则其它所有试图进入临界区的进程必须等待。
    3. 进入临界区的进程要在有限时间内退出,以便其它进程能及时进入自己的临界区。
    4. 如果进程不能进入自己的临界区,则应让出CPU,避免进程出现“忙等”现象。
  • 同步:进程中有内在的先后逻辑关系,如 进程2需要进程1运行的结果

  • 解决方法:

    • 忙等待:轮询检查资源是否可用
    • 睡眠与唤醒:无法工作转为睡眠状态

6.1 忙等待

  • 屏蔽中断:整个机器完全停滞,供一个进程使用

  • 锁变量:使用变量记录临界资源是否被使用,但容易引发进程冲突

  • 严格轮转法:两个进程同时访问一个变量(turn),0/1控制进入。但是会造成自己阻碍自己进入临界区。

  • peterson解法:

在这里插入图片描述

  1. 进程0通过调用enter_region()进入临界区,此时1也想调用enter_region()来进入临界区, 但interested[0]为TRUE,因此被while循环挂起,当进程0出临界区时调用leave_region(),将 interested[0]设为FALSE,进程1即可及时进入临界区。
  2. 当进程0在调用enter_region()过 程的任意时刻被中断,进程1进入临界区后进程0再次进行时,依然会被挂起。(实际上while 循环体中的两条判断句就保证了,当一个进程在临界区中时,另一个想进入临界区的进程必然会被挂起)

限制:只使用于两个进程。

  • TSL指令:先把lock的值拷贝到寄存器,同时更改lock为1。优点lock的检查和更改在一个指令中,保证操作原子性。

6.2 睡眠与唤醒

信号量(semaphore):包含一个整数一个等待队列,与临界资源(打印机、扫描仪、内存中的一个变量等)一一对应。等待队列就是等待使用该资源的进程,当一个进程离开时,会检查该资源的等待队列。信号量正为可用个数,负为等待使用进程个数。

PV原语:操作信号量的代码,操作系统底层提供解决方案,使其不可分割,执行起来短小精悍。P下降,V上升(出自荷兰语)。

//进入临界区之前进程执行P原语
P (Semaphore s) {
    s=s-1;
    if (s<0){
		//增加到等待队列
    }
}
//离开临界区之后执行V原语
V (Semaphore s) {
    s=s+1;
    if (s<=0){
        //唤醒等待队列的进程		
    }
}
/*
假如有一台打印机,现在S=1,打印机的任务代码为
P(S)
print(process,doc)
V(S)
a、b、c三个进程来打印,我们假设过程如下
*/
  1. a 开始打印,首先执行P(S),s=s-1=1-1=0,没有空闲的资源,没有等待打印的进程,此时a进入print(a,doc),进行打印操作,此时等待队列和s变化状态如下

    s = 1 -> 0
    等待队列:
    
  2. 此时b进程到达,P(S),s=s-1=0-1=-1,此时s<0 进入阻塞态,b进入等待队列

    s = 1 -> 0 -> -1
    等待队列: b
    
  3. 此时c进程到来,执行P原语,s=s-1=-1-1=-2,此时s<0 进入阻塞态,c进入等待队列

    s = 1 -> 0 -> -1 -> -2
    等待队列: b - c
    
  4. 此时s=-2,代表有两个进程正在等待,假设此时a打印结束,a离开打印机的临界区,执行V原语,s=s+1=-2+1=-1,代表只有一个进程等待,s=-1≤0,所以a会唤醒等待队列中的一个进程,b状态改变为Ready,等待被调度器调度

    s = 1 -> 0 -> -1 -> -2 -> -1
    等待队列:  c
    
  5. b也打印完成,执行V原语,s=s+1=-1+1=0,s=0≤0,所以b在临走时唤醒c

    s = 1 -> 0 -> -1 -> -2 -> -1 -> 0
    等待队列:  
    
  6. c打印完成,执行V原语,s=s+1=1>0,所以c直接离开

    s = 1 -> 0 -> -1 -> -2 -> -1 -> 0 -> 1
    等待队列:  
    

PV原语同样适合忙等待

P (Semaphore s){
    while (!s>0){
        //放弃CPU,重新排队
    }
    s--;
}
V (Semaphore s){
    s++;
}

我们假设相同情况

  1. a开始打印,s=1>0,跳过while,s–,s变为0
  2. b要打印,执行P原语,进入while循环,轮询s状态
  3. c要打印,执行P原语,进入while循环,轮询s状态
  4. a打印完,执行V原语,s++,s=1
  5. b或者c可以运行,调度其中一个运行
  6. 剩下的进程运行

7)通信

7.1 进程间通信

  • 信号(Signal):不同整数代表不同含义,如9代表kill

  • 管道(Pipes):单向通信,分为无名管道和有名管道,无名管道:有族亲关系进程之间的通信,有名管道:没有族亲关系的进程之间的通信

  • 其他:消息队列(message)、信号量(semaphore)、共享内存(shared memory)、sockets(适用于不同机器上的通信)

7.2 线程间通信

一个进程中多个线程天然共享进程的资源,使用POSIX提供的Pthreads函数保证资源不会被同时访问到。

在这里插入图片描述

8)死锁

8.1 死锁概念及特点

有些资源不可被多个进程同时使用,对于资源的获取,可以使用P原语申请相关资源的信号量,在对于多个资源的申请上有可能造成死锁。例:

进程a,b,需要临界资源12
    a->1->2
    b->2->1
执行过程
	a->1
    b->2
    a->2(等待b)
    b->1(等待a,形成死锁)

特点:

  1. 循环等待
  2. 不能抢夺
  3. 拥有部分,期望更多
  4. 资源互斥使用

8.2 死锁的检查与恢复

  • 鸵鸟算法:死锁现象发生概率很低,解决困难,处理代价大。当死锁问题偶然出现时,手工干预(重启机器)

  • 检测方法:

  1. 建立有向图,判断途中是否存在有向环。

    下图表示进程A期望资源B

    A
    B

    下图表示进程C拥有资源D

    D
    C

    下图表示死锁状态(A拥有D,期望B,C拥有B,期望D)

    A
    B
    C
    D
  2. 拥有矩阵:矩阵Aij元代表第i个进程拥有第j个进程

    期望矩阵:矩阵Aij元代表第i个进程期望第j个进程

  • 解决方法:杀死一个最年轻的进程、进程回滚、抢夺资源。

8.3 死锁的避免和预防

避免方法:

  • 轨迹图法:不适于多资源多进程

在这里插入图片描述

  • 银行家算法:最大限度保证安全状态

    安全序列:存在一个分配回收的过程使得所有进程都能执行完

    安全状态:如果一个状态存在一个或多个安全序列就叫做安全状态

    安全状态:

在这里插入图片描述

非安全状态

在这里插入图片描述

死锁预防,针对死锁特点,预防方法如下:

  1. 循环等待→资源有序申请,把资源排序,逐步申请
  2. 不能抢夺→强行拿走资源
  3. 拥有部分,期望更多→使进程拥有全部资源
  4. 资源互斥使用→添加任务队列
发布了8 篇原创文章 · 获赞 0 · 访问量 1681

猜你喜欢

转载自blog.csdn.net/Pure_vv/article/details/102760642