zoukankan      html  css  js  c++  java
  • [ 操作系统 ] 第二章 —— 进程管理

    进程管理

    进程与线程

    概念

    定义:进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。

    组成:

    1. PCB:进程存在的唯一标志。PID不同。
    2. 程序段:存放程序代码。
    3. 数据段:存放程序运行中的数据。

    组织形式:

    1. 链接方式:按照进程状态将PCB分为多个队列,链表连接方式。
    2. 索引方式:按照进程状态建立不同的索引表,表项指向PCB。

    特征:

    1. 动态性:最基本的特征。
    2. 独立性:进程是系统进行资源分配、调度的独立单位。
    3. 异步性、并发性、结构性。

    进程状态

    三种状态:运行状态、就绪状态、阻塞状态。

    状态转换:

    1. 不存在由(阻塞态——>运行态)和(就绪态——>阻塞态)的转换。
    2. (运行态——>阻塞态)是主动的过程,(阻塞态——>就绪态)是被动的过程。

    进程控制

    概念:

    1. 通过进程控制来实现进程状态转换。
    2. 原语需要一气呵成,不可中断。关中断、开中断。

    相关原语:创建、终止、阻塞、唤醒、切换。

    进程通信

    共享存储:设置一个共享空间,但需要保证进程的互斥访问。

    1. 基于数据结构的共享:只能存储某种数据结构的数据。
    2. 基于存储区的共享:高级共享。

    管道通信:设置一个管道,即缓冲区,进行读写操作。

    1. 进行半双工通信(单向),互斥访问。
    2. 写满时,不能再写。读空时,不能再读。
    3. 没写满,不能读。没读空,不能写。

    消息传递:结构化消息,含消息头(发送方、接收方等进程信息)、消息体。

    1. 直接通信方式:消息挂到接收方的消息队列中。
    2. 间接通信方式:发到信箱。
    3. 使用发送/接收原语。

    线程

    线程属性:

    1. 线程成为CPU分配的基本单位,进程是资源分配的单位。
    2. 同一进程的不同线程共享资源,共享内存地址空间,不需要系统干预。
    3. 同一进程内的线程切换不会引起进程的切换。
    4. 也有就绪、阻塞等状态。

    实现方式:

    1. 用户级线程 ;多对一模型:一个线程阻塞,会导致整个进程都被阻塞。
    2. 内核级线程 ;一对一模型:一个用户级线程对应一个内核级线程

    本节错题

    1. 优先级可以分为静态和动态两种,动态优先级可根据运行情况随时调整,而不是不可改动的。

    2. 系统发生死锁时,有可能进程全都处于阻塞态,或无进程任务。因此,并非任何时刻都有进程处于运行态。

    3. 程序是静态的,进程是动态的。不可将两者相互描述。

    4. 新进程进入就绪态,不会导致运行态转变为其他状态。

    5. 进程的就绪数目越多,争夺CPU的进程就越多,但只要就绪队列不为空,CPU就总是可以调度进程运行,保持繁忙。这与就绪进程的数目没有关系,除非就绪队列为空,此时CPU进入等待态,导致CPU的效率下降。

    6. 由于引入线程后,线程变为处理机调度的基本单位,因此,同一进程或不同进程的线程都可以并发执行。

    7. 降低进程优先级的时机:进程的时间片用完。提高优先级的时机:进程完成IO操作进入就绪队列、长期处于就绪状态。

    8. 进程被唤醒,进入就绪状态,而不是运行态。优先级可能被适当提高。

    9. 进程可以创建进程或线程,线程也可以创建线程,但线程不能创建进程。

    处理机调度

    概念

    调度:从就绪队列中按照一定的算法选择一个进程,并将CPU分配给他。

    三种调度:

    1. 高级调度(作业调度):选择合适的作业调入内存。(外存 ==》内存,面向作业)
    2. 中级调度(内存调度):从挂起的队列中选择合适的进程调入内存。(外存 ==〉内存,面向进程)
    3. 低级调度:为进程分配处理机。

    进程调度

    进程调度的主动与被动:

    1. 主动放弃:进程正常终止、运行过程中发生异常而终止、主动阻塞。
    2. 被动放弃:时间片用尽、优先级更高的进程、更紧急的进程。

    不能进行进程调度:进程在操作系统内核程序临界区;处理中断;原语过程。

    评价指标

    系统吞吐量:单位时间内完成作业的数量。

    [系统吞吐量 = frac{总共完成了多少道作业}{总共花了多少时间} ]

    周转时间:从作业被提交给系统,到最后完成为止的时间间隔。

    带权周转时间:值越小,满意度越高。必然>=1。

    [周转时间 = 作业完成时间 - 作业提交时间 \ 平均周转时间 = frac{各作业周转时间之和}{作业数}\ 带权周转时间 = frac{作业周转时间}{作业实际运行时间}\ 平均带权周转时间 = frac{各作业带权周转时间和}{作业数} ]

    调度算法

    先来先服务FCFS:按照到达的先后顺序调度,事实上就是等待时间越久的越优先得到服务。

    优点:公平、算法实现简单。非抢占式。

    缺点:对长作业有理,对短作业不利。

    短作业优先SJF:最短的作业或进程得到服务。如果运行时间相同,则选择先到达的进程运行。

    最短剩余时间优先:比较新进程和正在运行的进程的剩余时间。(抢占式)

    缺点:对短作业有利,长作业不利。会导致饥饿现象,源源不断的短作业等,则长作业长时间得不到服务。

    高响应比优先HRRN:不会导致饥饿。

    [响应比 = frac{等待时间+要求服务时间}{要求服务时间} ]

    时间片轮转RR

    1. 轮流让各个进程执行一个时间片,若在一个时间片内未执行完成,则剥夺处理机。
    2. 用于进程调度。(只有作业放入内存建立了相应的进程后,才能被分配处理机时间片)
    3. 抢占式算法;时钟中断宣布时间片到。
    4. 在运行过程中,如果同一时刻,既有进程下处理机,又有新进程到达,则默认新到达的进程先进入就绪队列。
    5. 如果时间片太大,时间片轮转调度算法退化为先来先服务调度算法,会增大进程相应时间。时间片太小,又会导致进程切换过于频繁。
    6. 不会导致饥饿。

    优先级调度算法

    1. 每个作业、进程都有各自的优先级,调度时选择优先级高的。
    2. 如果进程在就绪队列等了太长时间,可以适当提高其优先级。如果一个进程频繁进行IO操作,可以适当提高。
    3. 优点:用优先级区分紧急程度,适用于实时操作系统。可灵活地调整对各个作业的偏好程度。
    4. 会导致饥饿。

    多级反馈队列调度算法

    1. 用于进程调度;抢占式算法。
    2. 设置多级就绪队列,各级队列优先级从高到低,时间片从小到大。
    3. 若用完时间片,进程还未结束,则进程进入下一级队列队尾。
    4. 只有第k级队列为空时,才会为k+1级队头的进程分配时间片。
    5. 被抢占处理机的进程重新放回原队列队尾。
    6. 会导致饥饿。源源不断短进程到达,被降级的优先级会长期得不到服务。

    进程同步与互斥

    概念

    进程同步:进程的直接制约关系,各个进程的工作推进需要遵循一定的先后顺序

    进程互斥:对临界资源的访问,需要互斥的进行。即同一时间段内只能允许一个进程访问该资源。

    1. 进入区检查并上锁。退出去解锁。
    2. 临界区访问临界资源的代码。剩余区时其余代码部分。
    3. 遵循原则:空闲让进、忙则等待、有限等待、让权等待(while循环等待)。

    进程互斥的软件实现方法

    单标志法

    1. 两个进程在访问完临界区后会把使用临界区的权限交给另一个进程。
    2. 根据例子可知,尽管临界区是空闲的,也有可能出现不允许另一进程访问的情况。
    3. 违背了空闲让进的原则。

    双标志先检查法

    1. 设置一个bool数组,数组中各个元素用来标记各进程是否想要进入临界区。flag[0]=true意味着0号进程现在想要进入临界区。
    2. 由于异步性,可能会导致进程同时访问临界区。违背了忙则等待原则。
    3. 原因在于:进入区的检查和上锁的处理不是一气呵成的。

    双标志后检查法

    1. 由于异步性,可能导致进程都无法进入临界区。
    2. 解决了忙则等待原则,但是又违背了空闲让进和有限等待的问题。会产生饥饿现象。

    Peterson算法

    1. 进入区:主动争取、主动谦让,检查对方是否谦让。
    2. 不遵循让权等待原则,会发生忙等。

    进程互斥的硬件实现方法

    中断屏蔽:“开/关中断指令”的实现。

    缺点:

    1. 不适合多处理机。比如现有某一进程正在访问临界区,而另一进程正在运行且需要访问同一临界区,就会导致冲突。
    2. 只适用于内核进程,不适用于用户进程。因为两指令权限很大。

    TestAndSet

    1. TSL指令是用硬件实现的,执行过程不允许被中断,只能一气呵成。
    2. 缺点:不满足让权等待原则,暂时无法进入临界区的进程会占用CPU并循环执行TSL指令,从而导致忙等。
    3. 记录以前的lock值,修改lock值。

    swap指令:逻辑上和TSL相同。

    信号量机制

    整型信号量:该整数表示某一资源的可用数量。

    记录型信号量semaphore:

    1. P操作:该进程请求一个单位的资源,先执行value--,若结果<0,说明该资源之前已经分配完毕,因此该进程需要调用block原语进行自我阻塞,即从当前运行的进程从(运行态 --> 阻塞态),主动放弃处理机,并插入该类资源的等待队列中。
    2. V操作:释放一个单位的资源,先执行value++,若结果<=0,说明此时仍然有进程在等待该类资源,应调用wakeup原语唤醒等待该资源的进程。(阻塞态 --> 就绪态)

    信号量实现互斥、同步

    互斥实现步骤

    1. 分析并发进程的关键活动,划定临界区。(比如说打印机是需要互斥访问,这类资源就应该放在临界区)
    2. 设置互斥信号量mutex,初值为1。(信号量的名字可以任意设置。而具体的值,则是根据资源数量而设置)
    3. 在临界区之前执行P(mutex)
    4. 在临界区之后执行V(mutex)

    注意

    1. 对不同的临界资源,需要设置不同的互斥信号量。
    2. P、V操作需要成对出现。缺少P导致不能保证资源的互斥访问。缺少V导致资源不被释放,进程不被唤醒。

    同步实现步骤(需要一前一后执行的操作):

    1. 分析什么地方需要实现同步关系。
    2. 在“前操作”之后执行V(S)
    3. 在“后操作”之前执行P(S)

    注意

    1. 执行完P、V操作后,S的结果还是0。
    2. 如果先执行P操作,会主动阻塞。然后在V操作中执行wakeup原语唤醒该阻塞进程。
    3. 如果先执行V操作,执行P操作时就知道,此时有可用资源。

    实现前驱关系:

    1. 要为每一对前驱关系各设置一个同步变量。 S1 ---> S2; S1 ---> S3....
    2. 根据自身情况,执行相应的P、V操作。

    生产者-消费者问题

    生产者消费者问题是一个互斥、同步的综合问题。

    解题要点

    1. 两对同步关系:有时候是消费者需要等待生产者生产、有时候是生产者要等待消费者消费。因此是两个同步信号量。

      如图所示,实际上,full 和 empty的名字不是我们的关注点。问题在于,根据箭头方向,决定两者的前后顺序。

    2. 一对互斥关系:对于临界区的访问,通常是为 1 的。

    3. 注意实现互斥和同步的两个P操作的先后顺序。如果任意的交换位置,可能会导致死锁现象,即相互等待。

    多生产者-多消费者问题

    1. 不设置专门的mutex,也不会出现多个进程同时访问盘子的现象的原因:

    答:当缓冲区的大小为1时,在任何时刻,多类同步信号量中最多只有一个是1,所以最多只有一个进程的P操作不会被阻塞,并且顺利地进入临界区。

    1. 如果把盘子(缓冲区)数量改成>=2:

      答:如果没有mutex,可能会导致缓冲区数据覆盖的情况,即两个进程同时访问同一块缓冲区。

    2. 要把对“行为动作”的分析转变成对事件的分析。 盘子变空 ===》放入水果。(不是很明白)

    吸烟者问题

    假设一个系统有三个抽烟者进程和一个供应者进程。

    同步关系:四个同步关系。

    互斥关系:桌子可以抽象为容量为1的缓冲区。且有三种组合。

    这里我有点疑问。为什么producer的P操作不是放在if语句之前。
    image-20200228221228252

    读者-写者问题

    问题描述:

    1. 允许多个读者同时对文件执行读操作。
    2. 只允许一个写者往文件中写信息。
    3. 任一写者在完成写操作之前不允许其他读者或写者工作。
    4. 写者执行写操作前,应让已有的读者和写者全部退出。

    主要思想:

    1. 其核心思想在于设置了一个计数器count用来记录当前正在访问共享文件的读进程数。我们可以用count的值来判断当前进入的进程是否是第一个(进行加锁)/最后一个(进行解锁)进程。
    2. 又由于count变量的检查和赋值不能一气呵成,从而导致某些错误,因此要借助互斥信号量。

    哲学家问题

    问题描述:

    1. 哲学家进餐问题的关键在于解决进程死锁:进程之间只存在互斥关系,而此时每个进程都需要同时持有两个临界资源,因此就有死锁的可能。
    2. 对于解决方案:各哲学家拿筷子这件事必须互斥的进行。这就保证了即使一个哲学家在拿筷子拿到一半时被阻塞,也不会有别的哲学家会继续尝试拿筷子。这样的话,当前正在吃饭的哲学家放下筷子后,被阻塞的哲学家就可以获得等待的筷子了。

    管程

    管程的引入:解决信号量机制编程麻烦的问题,更好地实现同步互斥。

    基本特征:

    1. 管程中需要定义共享数据结构,对其初始化,再定义一组用来访问该结构的函数。
    2. 各外部进程/线程只能通过管程提供的特定入口才能访问共享数据。
    3. 每次仅允许一个进程在管程内执行某个内部过程。

    补充:

    1. 这种互斥特性是由编译器负责实现的。
    2. 可在管程中设置条件变量及等待/唤醒操作以解决同步问题。

    死锁

    概念

    死锁、饥饿、死循环

    共同点:都是进程无法顺利向前推进

    不同点:

    1. 死锁是“循环等待对方手里的资源”导致。因此必须要有两个或两个以上的进程同时发生死锁。发生死锁的进程一定处于阻塞态。
    2. 饥饿可能只有一个进程发生饥饿。发生饥饿的进程即可能是阻塞态(等待io设备),也可能是就绪态(长期得不到处理机)。
    3. 死循环是被管理者的问题,是可以上处理机上运行的。死锁和饥饿是管理者进行调度方案不佳的问题,处于核心态。

    死锁产生的必要条件

    1. 互斥条件:对必须互斥使用的资源争抢。
    2. 不剥夺条件:只能是进程主动释放资源,不可剥夺。
    3. 请求和保持条件:保持某种资源不放的同时,请求别的资源。
    4. 循环等待条件:存在一种进程资源的循环等待链条。循环等待未必死锁。

    处理死锁的策略

    1. 预防死锁:破坏产生条件。
    2. 避免死锁:避免系统进入不安全状态。
    3. 死锁的检测和解除:允许死锁发生,系统负责检测出死锁并解除。

    预防死锁

    四种方法与各自缺点

    破坏互斥条件 方法 缺点
    破坏不剥夺条件 申请资源得不到满足时,立即释放拥有的所有资源;申请的资源被其他进程占用时,由操作系统协助剥夺。 可行性不高。
    破坏请求和保持条件 运行前分配好所有需要的资源,之后一直保持。 剥夺资源可能导致部分工作实效;反复申请和释放导致系统开销大;导致饥饿。
    破坏循环等待条件 给资源编号,必须按编号从小到大的顺序申请资源。 资源利用率低;可能导致饥饿。
    破坏互斥条件 将临界资源改造为可共享使用的资源(SPOOLing技术)。 不方便增加新设备;会导致资源浪费。

    避免死锁

    银行家算法步骤:

    1. 检查此次申请是否超过了之前声明的最大需求数。
    2. 检查此时系统剩余的可用资源是否还能满足这次请求。
    3. 试探分配,修改数据结构
    4. 用安全性算法检查此次分配是否会导致系统进入不确定状态。

    安全性算法步骤:

    1. 检查当前的剩余可用资源是否能满足某个进程的最大需求,如果可以,则将他加入安全序列,并把该进程持有的资源全部回收。
    2. 不断重复上述过程,看最终是否能让所有进程都加入安全序列。

    系统处于不安全状态未必死锁,但死锁一定处于不安全状态。

    死锁的检测和解除

    死锁检测算法:

    1. 依次消除与不阻塞进程相连的边,直到无边可消,求出安全序列。
    2. 若资源分配图时不可完全简化的,说明发生了死锁。

    死锁的解除:

    1. 资源剥夺法:挂起死锁进程,并抢占它的资源。
    2. 撤销进程法:强制撤销部分或全部进程。又可能导致功亏一篑。
    3. 进程回退法:让一个或多个死锁进程回退到足以避免死锁的地步。这需要系统记录进程的历史信息,设置还原点。
  • 相关阅读:
    html+php超大视频上传功能
    html+php超大视频上传教程
    html+php超大视频上传方案
    html+php超大视频上传技术
    html+php超大视频上传实例解析
    html+php超大视频上传示例
    html+php超大视频上传实例
    矩阵求导
    概率密度
    概率分布函数
  • 原文地址:https://www.cnblogs.com/recoverableTi/p/12382554.html
Copyright © 2011-2022 走看看