第2章 进程管理

 

 

  • 2.1 进程与线程
    • 2.1.1 进程的概念
      • 1. 进程的概念
        • 为什么要引入进程:为了更好地描述和控制程序的并发执行。
        • 什么是进程:进程是进程实体的一次运行,是系统进行资源分配和调度的一个独立单位
        • 什么是进程实体:进程实体由程序段、相关数据段和PCB三部分构成,也称为进程映像。 注意:进程映像是静态的,进程则是动态的。
        • 进程控制块(PCB):保存进程运行期间相关的数据,是进程存在的唯一标志。
        • 程序段:能被进程调度程序调度到CPU运行的程序的代码段。
        • 数据段:存储程序运行期间的相关数据,可以是原始数据,也可以是程序执行时产生的中间或最终结果。
        • 什么是处理机:处理机是处理计算机系统中存储程序和数据,并按照程序规定的步骤执行指令的部件。
        • 程序是描述处理机完成某项任务的指令序列。
        • 指令则是处理机能直接解释、执行的信息单位。
      • 2. 进程的特征
        • 进程与程序的区别

        • 进程的基本特征
        • (1)动态性。进程是程序的一次执行,具有创建、活动、终止等过程,是动态地产生、变化和消亡。动态性是进程最基本的特征,是区别于程序的根本特征。
        • (2)并发性。指多个进程实体能够同时存在于内存中,能在一段时间内同时运行。
        • (3)独立性。指进程实体是一个能够独立运行、独立获得资源和独立接受调度的基本单位。
        • (4)异步性。指进程以不可预知的速度向前推进,内存中的每个进程何时执行,何时暂停,以怎样的速度向前推进,每道程序总共需要多少时间才能完成等都是不可预知的。异步性导致执行结果具有不可再现性,需要配置相应的同步机制才会多次运行得出相同结果。 异步是指进程之间有制约关系,进程A需要用打印机,如果进程B占用了打印机,就要等一等,进程A就会表现出走走停停、以不可预知的速度前进。
        • (5)结构性。指进程实体由程序段、数据段和PCB三部分组成。
    • 2.1.2 进程的状态与转换
      • 进程的状态种类
        • 创建状态:进程正在被创建,尚未转到就绪状态。
        • 就绪状态:进程已经获得除处理机之外的一切所需资源。
        • 运行状态:进程正在处理机上运行。 在单处理机环境下,每个时刻最多只有一个进程处于运行态。比如说单处理系统中,若同时存在10个进程,那么不可能出现10个进程都处于就绪或运行状态,可能是9个处于就绪状态、1个处于运行状态或者可能10个进程都处于阻塞状态。​
        • 阻塞状态(等待状态):进程正在等待某一事件而暂停运行。 某一事件可能是等待某资源(不包括处理机)或等待输入输出的完成。注意,即使处理机空闲,进程也不能运行。
        • 结束状态:进程正从系统中消失,分为正常结束和异常退出。 注意,必须先将进程置为结束态,才能释放回收资源。
      • 进程的状态变化
        • 三中基本状态之间的切换

        注意:一个进程从运行态变成阻塞态是主动的行为;而从阻塞态变成就绪态是被动的行为,需要其他相关进程的协助。

    • 2.1.3 进程的控制
      • 创建:终端用户登陆系统、作业调度、系统提供服务、用户程序的应用请求等。
      • 终止:正常结束、发生异常、外界干预。
        • 正常结束:进程的任务完成。
        • 异常结束:如存储区越界、保护错、非法指令、特权指令错、运行超时、算术运算错、I/O故障等。
        • 外界干预:操作员或操作系统干预、父进程请求和父进程终止。
      • 阻塞:等待资源。
      • 唤醒:资源到达。
      • 切换:时间片用完、主动放弃处理机、被更高优先级的进程剥夺处理机。 进程的切换指处理机从一个进程的运行转到另一个进程上运行。
    • 2.1.4 进程的组织
      • 1. 进程控制块(PCB) 进程是一个独立的运行单位,是操作系统进行资源分配和调度的基本单位。由以下三部分组成,其中最核心的是进程控制块PCB。
        • PCB是进程实体的一部分,是进程存在的唯一标志。操作系统通过PCB表来管理和控制进程。PCB主要包括进程描述信息、进程控制和管理信息、资源分配清单和处理相关信息。
      • 2. 程序段
        • 程序可被多个进程共享,即多个进程可以运行通过一个程序。
      • 3. 数据段
        • 一个进程的数据段,可以是原始数据,也可以是程序执行时产生的中间或最终结果。
    • 2.1.5 进程的通信
      • 概念:进程通信是指进程之间的信息交换。PV操作是低级通信方式,高级通信方式是指以较高的效率传输大量数据的通信方式,包括以下三类:共享存储、消息传递和管道通信。
      • 高级通信方法
        • (1)共享存储
        • 共享存储的分类
        • 低级方式的共享是基于数据结构的共享
        • 高级方式的共享是基于存储区的共享
        • 理解
        • 甲和乙中间有一个大布袋,甲和乙交换东西都是通过布袋进行的,甲把东西放在布袋里,乙拿走。但乙不能直接到甲手中拿东西,甲也不能直接到乙的手中拿东西。

        • (2)消息传递
        • 消息传递分类
        • 直接通信方式:直接把消息挂到接收进程的消息队列中。
        • 间接通信方式:挂到某个中间实体,接收进程找实体接收消息,类似于电子邮件。
        • 理解
        • 甲要告诉乙某些事情,就要写信,然后通过邮差送给乙。直接通信就是邮差直接把信交到乙的手上;间接通信就是乙家门口有个邮箱,邮差把信放到邮箱里。
        • (3)管道通信
        • 利用一种特殊的pipe文件连接两个进程。是一种半双工通信。
    • 2.1.6 线程概念和多线程模型
      • 1. 线程的基本概念
        • 引入目的:为了更好的使多道程序并发执行,以提高资源利用率和系统吞吐量,增加程序的并发性。
        • 特点
        • 线程由线程ID程序计数器寄存器集合堆栈组成。
        • 线程自己不拥有系统资源,只拥有一点儿运行中必不可少的资源。
        • 与同进程中的其他线程共享进程所拥有的全部资源。
        • 一个线程可以创建和撤销另一个线程,同一进程中多个线程可以并发执行。
        • 线程也有就绪、阻塞和运行三种基本状态。
        • 引入线程后,进程只作为除CPU外的系统资源的分配单元,而线程作为处理机的分配单元。
        • 一个进程中有多个线程,若线程的切换发生在同一个进程中,只需要很少的时空开销。
        • 为什么线程的提出有利于提高系统并发性:由于有了线程,线程切换时,有可能会发生进程切换,也有可能不发生进程切换,平均而言每次切换所需的开销就变小了,因此让更多的线程参与并发,而不会影响到响应时间等问题。
      • 2. 线程与进程的比较 我们使用打开一个微信软件,这个时候就开启了一个进程,当我们在微信里面进行各种操作(查看朋友圈,扫一扫…),这么多的操作就是线程。
        • 比较总结

      • 3. 线程的属性
        • (1)线程不拥有系统资源,但每个线程都应有一个唯一的标识符和一个线程控制块,线程控制块积累了线程执行的寄存器和栈等现场状态。
        • (2)不同的线程可以执行相同的程序。
        • (3)同一进程中的各个线程共享该进程所拥有的资源。
        • (4)线程是处理机的独立调度单位,多个线程是可以并发执行的。
        • (5)一个线程被创建后,便开始了它的生命周期,包括阻塞状态、就绪状态和运行状态直到终止等各种状态变化。
      • 4. 线程的实现方式
        • 用户级线程:有关线程管理(如线程的创建、撤销和切换等)的所有工作都是在应用程序完成内核意识不到线程的存在
        • 内核级线程:线程管理的所有工作由内核完成。
      • 5. 多线程模型
  • 2.2 处理机调度
    • 2.2.1 调度的概念
      • 1. 调度的基本概念
        • 进程调度的原因:若没有调度,则需要等当前进程完成后,才能执行下一个进程,在实际情况中,进程时常需要等待一些外部设备的输入,而外部设备的输入与处理机相比是很慢的,若让处理机总等外部设备,则是对处理机资源的极大浪费。引进处理机调度后,在运行进程等待外部设备时,可以把处理机调度给其他进程,从而提高处理机的利用率。简单的来说,就是合理地处理计算机的软/硬件资源。 通俗易懂的来说,就是由于你正在下载一个电子书,要下载完成后才能阅读,但在这期间你不可能一直等在电脑前直到电子书下载完成,这将是对你时间的极大浪费,这时候你可以把你的时间分配到其他地方去(如听音乐、打电话等)。
        • 进程调度的概念:是对处理机进行分配,即从就绪队列中按一定算法(公平、高效)选择一个进程并将处理机分配给它运行,以实现进程并发运行。
      • 2. 调度的层次
        • 作业调度(高级调度):选择处于后备状态的作业分配资源,发生频率最低。
        • 内存调度(中级调度):选择暂时不能运行的进程调出内存,发生频率中等。 作用是提高内存利用率和系统吞吐量。哪些暂时不能运行调至外存等待的进程状态就做挂起态。
        • 进程调度(低级调度):选择就绪队列中合适的进程分配处理机,发生频率最高。
      • 3. 三级调度的联系
        • (1)作业调度为进程活动作准备,进程调度使进程正常活动起来,中级调度将暂时不能运行的进程挂起,中级调度处于作业调度和进程调度之间。
        • (2)作业调度次数最少,中级调度次数略多,进程调度频率最高。
        • (3)进程调度是最基本的,不可或缺。
    • 2.2.2 调度的时机、切换与过程 进程调度和切换程序是操作系统内核程序。
      • 不能进行进程的调度与切换的情况: 发生了下述情况,不能马上进行调度和切换,而是应置系统的请求调度标志,直到下述过程结束才进行相应的调度与切换。
        • (1)在处理中断的过程中。
        • (2)进程在操作系统内核程序临界区中。
        • (3)其他需要完全屏蔽中断的原子操作过程中。如加锁、解锁、中断现场保护、恢复等原子操作。 在原子过程中,连中断都要屏蔽,更不应该进行进程调度与切换。
      • 应该进行进程的调度与切换的情况:
        • (1)发生引起调度条件且当前进程无法继续运行下去时,可以马上进行调度与切换。若操作系统只在这种情况下进行进程调度,则是非剥夺调度。
        • (2)中断处理结束或自陷处理结束后,返回被中断进程的用户态程序执行现场前,若置上请求调度标志,即可马上进行进程调度与切换。若操作系统支持这种情况下的运行调度程序,则实现了剥夺方式的调度。
    • 2.2.3 进程调度方式
      • 进程调度方式的概念:是指当某个进程正在处理机上执行时,若有某个更为重要或紧迫的进程需要处理,即优先级更高的进程进入就绪队列,此时改如何分配处理机。
      • 两种进程调度方式
        • (1)非剥夺调度方式(非抢占式):有更为重要或紧迫的进程需要使用处理机,仍让当前进程继续执行。
        • 优点:实现简单、系统开销小,适用于大多数的批处理系统。
        • 缺点:不能用于分时系统和大多数的实时系统。
        • (2)剥夺调度方式(抢占式):有更为重要或紧迫的进程需要使用处理机,立即分配。
        • 优点:提高系统吞吐率和响应效率,适用于分时系统和实时系统。
    • 2.2.4 进程调度的基本准则
      • (1)CPU利用率。要尽可能使CPU处于忙的状态,使CPU利用率最高。
      • (2)系统吞吐量。表示单位时间内CPU完成作业的数量。长作业消耗处理机较长时间,降低了系统的吞吐量,短作业消耗处理机较短时间,提高了系统的吞吐量。调度算法和方式的不同会对系统的吞吐量产生较大影响。
      • (3)周转时间。是指从作业提交到作业完成所经历的时间。
        • 作业周转时间公式:周转时间 = 作业完成时间 — 作业提交时间。
        • 平均周转时间是指多个作业周转时间的平均值:平均周转时间 = (作业1的周转时间 + … + 作业n的周转时间)/ n。
        • 带权周转时间是指作业周转时间与作业实际运行时间的比值:带权周转时间=作业周转时间/作业实际运行时间。
        • 平均带权周转时间是多个作业带权周转时间的平均值:平均带权周转时间 = (作业1的带权周转时间 + … + 作业n的带权周转时间)/ n。
      • (4)等待时间。指进程处于等处理机状态的时间之和。处理机调度算法实际上并不影响作业执行或输入/输出的时间,只影响作业在就绪队列中等待所花的时间。
      • (5)响应时间。指用户提交请求到系统首次产生响应所用的时间。
    • 2.2.5 典型的调度算法
      • 0. 各种调度算法总结
        • 几种常见进程调度算法的特点

      • 1. 先来先服务(FCFS)调度算法
        • 算法描述:选择最先进入就绪队列中的作业(进程)。
        • FCFS调度算法的特点:
        • FCFS算法属于不可剥夺算法。
        • 不能作为分时系统和实时系统的主要调度策略。
        • 算法简单,但效率低;对长作业比较有利,但对短作业不利(相对SJF和高响应比);有利于CPU繁忙型作业,而不利于I/O繁忙型作业。
        • FCFS调度算法的性能:顺序是作业①——②——③——④。

      • 2. 短作业优先(SJF)调度算法
        • 算法描述:选择运行时间最短的作业(进程)。
        • SJF算法的特点:
        • 该算法对长作业不利。
        • 不能保证紧迫性作业会被及时处理。
        • 由于作业的长短由用户所提供的估计执行时间而定,致使算法不一定真正做到短作业优先调度。
        • 算法的平均等待时间、平均周转时间最少。
        • SJF算法的性能:顺序是作业①——④——③——②。

      • 3. 优先级调度算法
        • 算法描述:选择优先级最高的作业(进程)。 优先级指用于描述作业运行的紧迫程度。
        • 进程优先级分类 根据进程创建后其优先级是否可以改变,分为如下两种:
        • (1)静态优先级。优先级是在创建进程时确定的,且在进程的整个运行期间保持不变。确定静态优先级的主要依据有进程类型、进程对资源的要求、用户要求。
        • (2)动态优先级。在进程运行过程中,根据进程情况的变化动态调整优先级。动态调整优先级的主要依据有进程占有CPU时间的长短、就绪进程等待CPU时间的长短。
        • 进程优先级设置原则:
        • (1)系统进程 > 用户进程。 系统进程作为系统的管理者,理应有更高的优先级。
        • (2)交互型进程 > 非交互型进程(前台进程 > 后台进程)。 交互的进程应该更快被优先处理。
        • (3)I/O型进程 > 计算型进程。 频繁使用I/O设备的进程应该有更高的优先级,会让I/O设备尽快地投入工作。
      • 4. 高响应比优先调度算法
        • 算法描述:选择响应比最高的,主要用于作业调度,是FCFS算法和SJF算法的综合平衡。
        • 响应比计算公式:响应比=(等待时间+执行时间)/ 执行时间。
        • 算法特点:
        • (1)作业等待时间相同时,要求服务时间越短,相应比越高,有利于短作业。
        • (2)要求服务时间相同时,作业的响应比由等待时间决定,等待时间越长,响应比越高,实现的是先来先服务。
        • (3)克服了饥饿状态,兼顾了长作业。
      • 5. 时间片轮转调度算法
        • 算法描述:总是选择就绪队列中的第一个进程,但仅能运行一个时间片。主要适用于分时系统。
        • 时间片的长短的决定因素:系统的响应时间、就绪队列中的进程数目和系统的处理能力。
      • 6. 多级反馈队列调度算法
        • 算法描述:时间片轮转调度算法和优先级调度算法的综合和发展。
        • 算法优势
        • (1)终端型作业用户:短作业优先。
        • (2)短批处理作业用户:周转时间较短。
        • (3)长批处理作业用户:经过前面几个队列得到部分执行,不会长期得不到处理。
    • 2.2.0 题目补充
      • (1)时间片轮转的主要目的是,使得多个交互的用户能够得到及时响应,使用户以为“独占”计算机的使用,因此它没有偏好,也不会对特殊进程进行特殊服务。时间片轮转增加了系统开销,所以不会使得系统高效运转,吞吐量和周转时间均不如批处理。但其较快速的响应时间使得用户能够与计算机进行交互,改善了人机环境,满足了用户需求。
      • (2)在单处理的多进程系统中,进程什么时候占用处理器及决定占用时间的长短由进程特点和进程调度策略决定的。
      • (3)若每个作业只能建立一个进程,为了照顾短作业用户,应采用短作业优先调度算法;为了照顾紧急作业用户,应采用剥夺式优先级调度算法;为了能够实现人机交互,应采用时间片轮转调度算法;而能使短作业、长作业和交互作业用户都满意,应采用多级反馈队列调度算法。
      • (4)处于运行态的进程用完一个时间片后,其状态会变为就绪态,等待下一次处理器调度。进程执行完最后的语句并使用系统调用exit请求操作系统删除它或出现一些异常情况时,进程才会终止。
      • (5)作业的优先权与长作业、短作业或系统资源要求的多少没有必然关系。在动态优先权中,随着进程执行时间的增加其优先权随之降低,随着作业等待时间的增加其优先权相应上升。
      • (6)时间片轮转算法是按固定时间配额来运行的,时间一到,不管是否完成,当前进程必须撤下,调用新的进程,因此它是由时间配额决定的,是绝对可抢占的。而优先级算法和短进程优先算法都可分为抢占式和不可抢占式。(即先来先服务、优先级、短进程优先算法都不是绝对可抢占式的。)
      • (7)作业与进程最主要的区别是,作业是用户提交的,进程是系统自动生成的。作业是以用户任务为单位,进程是操作系统控制的单位。
      • (8)采用时间片调度算法,当时间片过大时,就会使时间片轮转算法转化为先来先服务算法。
      • (9)采用静态优先级调度且系统总是出现优先级高的任务时,优先级低的任务总是得不到处理机而产生饥饿现象;而短任务优先调度不管是抢占式还是非抢占的,当系统总是出现新来的短任务时,长任务总是得不到处理机,也会产生饥饿现象。而时间片调度算法不可能产生饥饿现象。
      • (10)分时系统中,响应时间与时间片和用户数成正比,因此当分时系统的时间片固定时,用户数越多,响应时间越长。UNIX是一个强大的多用户、多任务操作系统,支持多宗处理器架构,按照操作系统分类,属于分时操作系统。中断向量本身是用于存放中断服务例行程序的入口地址,因此中断向量地址就应是该入口地址的地址。中断由硬件保护并完成,主要是为了保证系统运行可靠、正确,提高处理速度也是一个好处,但不是主要目的。
  • 2.3 进程同步
    • 2.3.1 进程同步的基本概念
      • 0. 进程同步
        • 引入目的:为了协调进程之间的相互制约关系。 例如1+2×3要求是先乘法再加法。但由于计算机操作系统的异步性,可能发生先加法后乘法的情况,而同步就是使计算机系统按照先乘法再加法的顺序进行。
      • 1. 临界资源
        • 临界资源:即一次仅允许一个进程使用的资源称为临界资源。 如打印机等物理设备及许多可以被若干进程共享的变量、数据等。
        • 把临界资源的访问过程分为四个部分:

        对临界资源的访问必须互斥(就是你正在访问那么我就不能访问了,我正在访问你就不能访问了)的进行。​

        • (1)进入区。在进入区要检查可否进入临界区,若能进入临界区,则应设置正在访问临界区的标志,以阻止其他进程同时进入临界区。
        • (2)临界区(又称临界段)。进程中访问临界资源的那段代码。
        • (3)退出区。将正在访问临界区的标志清除。
        • (4)剩余区。代码中的其他部分。
      • 2. 同步
        • 同步:即直接制约的关系,是指为完成某种任务而建立的量或多个进程,在位置上协调它们的工作次序。
      • 3. 互斥
        • 互斥:也称间接制约关系,当一个进程进入临界区使用临界资源时,另一个进程必须等待,当占用临界资源的进程退出临界区后,另一进程才允许访问此临界资源。 比如说打印问题。
        • 为了禁止两个进程同时进入临界区,同步机制应遵循以下原则:
        • (1)空闲让进。临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区。
        • (2)忙则等待。当临界区已有进程时,其他试图进入临界区的进程必须等待。
        • (3)有限等待。必须保证请求的进程在有限时间内能够进入临界区。
        • (4)让权等待。当进程不能进入临界区时,应立即释放处理机资源,防止进程忙等待。
    • 2.3.2 实现临界区互斥的基本方法
      • 1. 软件实现方法

      • (1)算法一:单标志法

      两个进程无法交替进入临界区(违背“空闲让进”):指的是当P0进入临界区又回来后,会将turn置为1,此时临界区是空闲的,允许P1进入临界区,但是问题来了,P1暂时不想进入临界区,而P0现在又想进入临界区了,可是turn现在为1只允许P1进入,导致P0不能进入,所以违背了“空闲让进”原则。

      • (2)算法二:双标志法先检查

      可能两个进程同时进入临界区(违背“忙则等待”):即检查对方的flag是否为TRUE和切换自己的flag为TRUE前有一段时间,可能发生结果都检查通过,问题是检查和修改操作要分两次完成而不能一次完成。P0现在想要进入临界区了,在进入之前,先检查P1是否在临界区,发现P1不在临界区它的flag为FALSE,表示此刻P0可以进入临界区,然后P0就准备将自己的flag置为TRUE表示正在临界区,但是问题来了,在P0修改成功之前,P1现在也想要进入临界区,检查P0的flag为FLASE(因为还没有修改成功),然后P0就认为自己被允许进入临界区,所以也修改自己的flag,最后就会导致两个进程P0和P1同时将自己的flag修改为TRUE,发生同时进入临界区的问题,违背“忙则等待”原则。

      • (3)算法三:双标志法后检查

      两个进程谁也不能进入临界区(“饥饿”现象):进程P0现在想要进入临界区,所以将自己的flag标志置为TRUE,然后检测P1进程的标志,这个时候(即未检测到P1状态之前),P1也想进入临界区,所以也将自己的flag标志置为TRUE,然后也检测P0的标志,问题来了,P0发现P1标志为TRUE,P1也发现P0标志为TRUE,都互相谦让,然后都不能进入,就会产生“饥饿”现象。

      • (4)算法四:Peterson’s Algorithm

      利用flag解决临界资源的互斥访问并且利用turn解决“饥饿”现象(是算法一和算法三的结合):P0将自己的flag标志设置为TRUE表示自己想要进入临界区,然后再设置turn=1表示允许P1进程进入临界区,检测只有当P1的flag标志为TRUE并且turn=1时表示P1已经在临界区,P0进程只能等待,若P1不想进入临界区,即它的flag标志为FALSE,则P0可以进入临界区。

      • 2. 硬件实现方法

      • (1)中断屏蔽方法

      • (2)硬件指令方法
      • TestAndSet指令:读出指定标志然后将该标志设置为真。这条指令属于原子操作,不允许被中断。
      • TestAndSet指令功能描述是:

      • 利用该指令实现进程互斥的算法描述如下:

      为每个临界资源设置一个共享布尔变量lock,表示资源的两种状态:true表示正被占用,初值为false表示未被占用。在进程访问临界资源之前,利用TestAndSet指令检查和修改标志lock;若有进程正在占用临界区,则反复检查,直到进程退出。

      • Swap指令:功能是交换两个字(字节)的内容。
      • Swap指令功能描述如下:

      • 利用该指令实现进程互斥的算法描述如下: 为每个临界资源设置一个共享布尔变量lock,初值为false;在每个进程中再设置一个局部布尔变量key,用于与lock交换信息。在进入临界区前,先利用Swap指令交换lock与key的内容,然后检查key的状态;有进程在临界区时,重复交换和检查过程,直到进程退出。
    • 2.3.3 信号量
      • 0. 概念
        • 信号量:用来解决互斥与同步问题的,它只能被两个标准的原语wait(S)和signal(S)访问,也可记为“P操作”和“V操作”。
        • 原语:是指完成某种功能且不被分割、不被中断执行的操作序列,通常由硬件实现。
      • 1. 整型信号量
      • 2. 记录型信号量
      • 3. 利用信号量实现同步 信号量机制能用于解决各种同步问题。
        • 例如,设S为实现进程P1、P2同步的公共信号量,初值为0。进程P2中的语句y要使用进程P1中语句x的运行结果,所以只有当语句x执行完成后语句y才能执行(即要先执行P1进程再执行P2进程,但由于操作系统的异步性,可能先执行P2进程再执行P1进程,所以需要进程同步来解决这个问题)。实现同步的算法如下:

        若P2先执行,在运行y语句之前就会执行P(S)检查,那么由于P1进程并没有执行,则S为0,执行P操作就会把进程P2阻塞,放入阻塞队列;当P1进程中的x语句执行完成后,执行到V(S)操作,把P2从阻塞队列中放回到就绪队列,当P2得到处理机时,得以继续执行。

      • 4. 利用信号量实现进程互斥 信号量机制也能解决进程互斥问题。​
        • 例如,设S为实现进程P1,P2互斥的信号量,由于每次只允许一个进程进入临界区,所以S的初值应为1(即可用资源数为1)。只需把临界区置于P(S)和V(S)之间,即可实现两个进程对临界资源的访问。实现互斥的算法如下:

        当没有进程进入临界区时,任意一个进程进入临界区,就要只需P操作,把S的值减为0,然后进入临界区;当有进程存在于临界区时,S的值为0,再有进程要进入临界区,执行P操作时将会被阻塞,直至临界区的进程退出,这便实现了临界区的互斥。

        • PV操作在同步互斥中的应用总结:
        • 在同步问题中,若某个行为需要用到某种资源,则在这个行为前P这种资源(即检查是否有这种资源);若某个行为会提供某种资源,则在这个行为后面V这种资源一下(即提供这种资源以便P操作检查)。
        • 在互斥问题种,P、V操作要紧夹使用互斥资源的哪个行为,中间不能有其他冗余代码。
      • 5. 利用信号量实现前驱关系 信号量机制也可以用来描述程序之间或语句之间的前驱关系。
        • 例如,如下图的前驱图,其中S1,S2,…,S6都是最简单的程序段,为使各程序段正常运行,应该设置若干初始值为“0”的信号量。

        • 第一步:分析关系

        • 第二步:实现算法如下

      • 6. 分析进程同步和互斥问题的方法步骤
        • (1)关系分析。找出问题的进程数,并分析它们之间的同步和互斥关系。同步、互斥、前驱关系直接按照上面例子中经典范式改写。
        • (2)整理思路。找出解决问题的关键点,并根据做过的题目找出求解的思路。根据进程的操作流程确定P操作、V操作的大致顺序。
        • (3)设置信号量。根据上面的两步,设置需要的信号量,确定初值,完善整理。
    • 2.3.4 管程
      • 0. 前言
        • 管程的引入:在信号量机制中,每个要访问临界资源的进程都必须自备同步的PV操作,大量分散的同步操作不便管理,而且容易因同步操作不当导致死锁,所以产生了新的进程同步工具——管程。
        • 管程的优点:保证了进程互斥,无须程序员自己实现互斥,降低了死锁发生的可能性。同时提供了条件变量,使程序员可以灵活地实现进程同步。
      • 1. 管程的定义
        • 管程的定义:由一组数据以及定义在这组数据之上的对这组数据的操作组成的软件。
        • 管程的组成:
        • ①管程的名称
        • ②局部于管程内部的共享结构数据说明。
        • ③对该数据结构进行操作的一组过程(或函数)
        • ④对局部于管程内部的共享数据设置初始值的语句
        • 管程的举例:
        • 举例:类似于Java语言中的类(class)结构

        • 管程的特点:
        • (1)管程把对共享资源的操作封装起来,一个进程只能通过调用管程内的过程才能进入管程访问共享资源。
        • (2)每次仅允许一个进程进入管程,从而实现进程互斥。
      • 2. 条件变量
        • 条件变量:即一个进程进入管程后被阻塞的原因定义为条件变量condition。 通常,一个进程有多个阻塞原因,故可以有多个条件变量。
        • 条件变量只能进行两种操作:wait和signal。
        • x.wait:当x对应的条件不满足时,正在调用管程的进程调用x.wait将自己插入x条件的等待队列,并释放管程。此时其他进程可以使用该管程。
        • x.signal:当x对应的条件发生了变化,则调用x.signal,唤醒一个因x条件而阻塞的进程。
        • 条件变量和信号量的比较

    • 2.3.5 经典同步问题
      • 1. 生产者-消费者问题 经典的同步互斥综合问题。
        • 问题描述:一组生产者进程和一组消费者进程共享一个初始为空、大小为n的缓冲区,只有缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区属于临界资源,它只允许一个生产者放入消息,或一个消费者取出消息。
        • 问题分析:
        • (1)关系分析。由于缓冲区属于临界资源故生产者和消费者对缓冲区的访问属于互斥访问,是互斥关系;由于必须先有生产者生成消息消费者才能取出消费,有先后顺序,所以又是同步关系。
        • (2)整理思路。进程:生产者进程和消费者进程;关系:同步和互斥关系。
        • (3)信号量设置。互斥访问缓冲区需要一个信号量mutex,初始值为1;信号量full记录当前缓冲池“满”缓冲区的个数,初始为0,这是题目设置的;信号量empty记录当前缓冲池“空”缓冲区的个数,初值为n,也是题目设置的。
        • 代码描述:
        • 第一步:初始化信号量

        • 第二步:写进程,有几个写几个

        • 第三步:在进程内写具体的PV操作

      • 1. 复杂的生产者-消费者问题
        • 问题描述:桌子上有一个盘子,每次只能向其中放入一个水果。爸爸转向盘子中放苹果,妈妈转向盘子中放橘子,儿子专等吃盘子中的橘子,女儿专等吃盘子中的苹果。只有盘子为空时爸爸或妈妈才能向盘子中放一个水果;仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出。
        • 问题分析:
        • (1)关系分析:由每次只可向其中放入一只水果可知爸爸和妈妈是互斥关系,对象盘子放水果是互斥的。爸爸和女儿、妈妈和儿子是同步关系,即要爸爸或妈妈要先放水果,女儿或儿子才能取水果吃,是先后顺序。儿子和女儿没有互斥和同步的关系,是选择条件执行,有需要的水果才吃。爸爸放苹果和女儿吃苹果、妈妈放橘子和儿子吃橘子必须连续执行。
        • (2)整理思路。这里有四个进程:爸爸进程、妈妈进程、儿子进程和女儿进程。可以抽象成两个生产者(爸爸和妈妈)和两个消费者(女儿和儿子)被连接到大小为1(只有一个盘子)的缓冲区上。
        • (3)信号量设置。信号量plate表示释放允许盘子放入水果,是互斥信号量。信号量apple表示盘子中是否有苹果,初值为0表示没有苹果可取;信号量orange表示盘子中是否有橘子,初值为0表示没有橘子可取。
        • 代码描述:
        • 第一步:初始化信号量

        • 第二步:写进程,有几个写几个

        • 第三步:在进程内写具体的PV操作

        dad()和daughter()、mom()和son()必须连续执行,也只能在女儿拿走苹果或儿子拿走橘子后才能释放盘子,即V(plate)操作。

        • 自己理解

      • 2. 读者-写者问题 读者-写者问题最关键的是有一个互斥访问的计数器count,如果遇到不好解决的同步互斥问题,可以考虑使用count能否解决。
        • 问题描述:有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不好产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:①允许多个读者可以同时对文件执行读操作;②只允许一个写者向文件中写信息;③任一写者在完成写操作之前不允许其他读者或写者工作;④写者执行写操作前,应让已有的读者和写者全部退出。
        • 问题分析: 读者写者问题最核心的问题是如何处理多个读者可以同时对文件的读操作。
        • (1)关系分析。读者和写者是互斥的;写者和写者也是互斥的;读者和读者不存在互斥关系。
        • (2)整理思路。两个进程,即读者进程和写者进程。写者和任何进程都互斥,用互斥信号量的PV操作解决。读者问题较为复杂,必须在实现与写者互斥的同时,实现与其他读者的同步,这里会用到一个计数器,用来判断是否有读者读文件。当有读者时,写者无法写文件,此时读者一直占用文件;当没有读者时,写者才可以写文件。不同读者对计数器的访问是互斥的。
        • (3)信号量设置。信号量count为计数器,用来记录当前读者的数量,初值为0,表示没有一个读者;信号量mutex为互斥信号量,用来保护更新count变量时的互斥,初值为1;信号量rw也为互斥信号量,用来保证读者和写者的互斥访问,初值为1。
        • 代码描述(读进程优先): 在下面的算法中,读进程是优先的,即当存在读进程时,写操作将被延迟,且只要有一个读进程活跃,随后而来的读进程都将被允许访问文件,可能导致写进程长时间等待,且存在写进程“饿死”的情况。
        • 第一步:初始化信号量

        • 第二步:写进程,有几个写几个

        • 第三步:在进程内写具体的PV操作

        • 代码描述(写进程优先): 如果希望写进程优先,即当有读进程正在读共享文件时,有写进程请求访问时,这时应禁止后续读进程的请求,等到已在共享文件的读进程完毕,立刻让写进程执行,只有在无写进程执行的情况下才允许读进程再次运行。解决方法就是增加一个信号量w并在上面的读进程优先的程序中的writer()和reader()函数中各增加一对PV操作。
        • 具体代码

        这里的写进程优先是相对而言的,也成为读写公平法,即读写进程具有一样的优先级。

      • 3. 哲学家进餐问题
        • 问题描述:一张圆桌边上坐着5名哲学家,每两名哲学家之间的桌上摆一根筷子,两根筷子中间是一碗米饭,如图2.10所示。哲学家们倾注毕生精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。若筷子已在他人手上,则需要等待。饥饿的哲学家只有同时拿到了两根筷子才可以开始进餐,进餐完毕后,放下筷子继续思考。

        • 问题分析:
        • (1)关系分析。五名哲学家与左右邻居对其中间筷子的访问是互斥关系。
        • (2)整理思路。五个哲学家进程。本题的关键是如何让一名哲学家拿到左右两根筷子而不造成死锁或饥饿现象。解决方法是:一是让他们同时拿两根筷子;二是对每名哲学家的动作制定规则,避免饥饿或死锁现象的发生。
        • (3)信号量设置。定义互斥信号量数组chopstick={1,1,1,1,1},用于对5个筷子的互斥访问。哲学家按顺序编号0~4,哲学家i左边筷子的编号为i,哲学家右边筷子的编号为(i+1)%5。
        • 代码描述(思考,可以这样吗?):

        • 代码描述(存在死锁问题):

        该算法存在以下问题:当五名哲学家都想要进餐并分别拿起左边的筷子时(都恰好执行完成wait(chopstick[i]);)筷子已被拿光,等到他们想要再拿起右边的筷子时(执行wait(chopstick[(i+1)%5]);)就全被阻塞,因此出现了死锁。

        • 代码描述(解决死锁方法):

        为了防止死锁发生,可以对哲学家进程添加一些限制条件,比如至多允许4名哲学家同时进餐;仅当一名哲学家左右两边的筷子都可用时,才允许他抓起筷子;对哲学家顺序编号,要求奇数号哲学家先拿左边的筷子,然后再拿右边的筷子,而偶数号哲学家刚好相反。下面的算法是第二种方法:当一名哲学家左右两边的筷子都可用时才允许抓起筷子。

      • 4. 吸烟者问题
        • 问题描述:假设一个系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停地卷烟并抽掉它,但要卷起并抽掉一支烟, 抽烟者需要有三种材料:烟草、纸和胶水。三个抽烟者中,第一个拥有烟草,第二个拥有纸,第三个拥有胶水。供应者进程无限地提供三种材料,供应者每次将两种材料放到桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它, 并给供应者一个信号告诉已完成,此时供应者就会将另外两种材料放到桌上,如此重复(让三个抽烟者轮流地抽烟)。
        • 问题分析:
        • (1)关系分析。供应者与三个抽烟者分别是同步关系。由于供应者无法同时满足两个或以上的抽烟者,三个抽烟者对抽烟这个动作互斥(或由三个抽烟者轮流抽烟得知)。
        • (2)整理思路。显然这里有4个进程。供应者作为生产者向三个抽烟者提供材料。
        • (3)信号量设置。信号量offer1、offer2、offer3分别表示烟草和纸组合的资源、烟草和胶水组合的资源、纸和胶水组合的资源。信号量finish用于互斥进行抽烟动作。
        • 代码描述
        • 第一步:初始化信号量

        • 第二步:写进程,有几个写几个

        • 第三步:在进程内写具体的PV操作

  • 2.4 死锁
    • 2.4.1 死锁的概念
      • 1. 死锁的定义
        • 是指多个进程因竞争资源而造成的一种僵局(互相等待)。 例如,进程P1和P2分别正在使用资源A和资源B,但是进程P1又提出请求正被P2使用的B资源,进程2又提出请求正被P1使用的A资源,这样两个进程相互无休止的等待下去,均无法继续执行,此时两个进程陷入死锁状态。
      • 2. 死锁产生的原因
        • (1)系统资源的竞争
        • 系统中拥有的不可剥夺资源的数量不足以满足多个进程运行的需要,因争夺资源而陷入僵局。 注意:只有对不可剥夺资源的竞争才可能产生死锁,对可剥夺资源的竞争不会产生死锁。
        • 系统中资源分为两类:
        • 可剥夺资源:指进程在获得这类资源后,该资源可以被其他进程或系统剥夺。例如CPU和主存都是可剥夺性资源。
        • 不可剥夺资源:当系统把这类资源分配给某进程后,再不能强行收回,只能在进程用完后自行释放,如磁带机、打印机等。
        • (2)进程推进顺序非法
        • 进程运行过程中,请求和释放资源的顺序不当,也会导致死锁。 例如:并发进程P1,P2分别占有了资源A和B,而进程P1又申请资源B、进程P2又申请资源A,两者都会因为所需资源被占用而阻塞。
        • 信号量使用不当也会造成死锁。 例如:进程A等待进程B的消息,进程B又在等待进程A发的消息,可以看出不是因为竞争同一资源,而是在等待对方的资源而导致死锁。
        • (3)死锁产生的必要条件 产生死锁必须同时满足以下四个条件,只要其中任意一个不成立,都不会产生死锁。
        • 互斥条件:即在一段时间内,某资源仅为一个进程所占有,在此期间若有其他进程请求该资源,只能排队等待。
        • 不剥夺条件:即进程所获得的资源在未用完之前不能被其他进程强行夺走,只能自己主动释放。
        • 请求并保持条件:即进程已经占有了至少一个资源,但又提出了新的资源请求,而所请求的资源被其他进程占有,故请求进程阻塞,而自己占有的资源又不释放。
        • 循环等待条件:存在一种进程资源的循环等待链,链中每个进程已获得的资源同时被链中下一个进程所请求。即存在一个等待态的进程集合{P1,P2,…,PN},其中P[i]等待的资源被P[i+1](i=0,1,…,n-1)占有,P[n]等待的资源被P[0]占有。
    • 2.4.2 死锁的处理策略 预防死锁和避免死锁都属于事先预防的策略。
      • 1. 死锁预防:设置某些限制条件,破坏产生死锁的四个必要条件中的一个或几个,以防止发生死锁。
      • 2. 避免死锁:在资源的动态分配中,用某种方法防止系统进入不安全状态,从而避免死锁。
      • 3. 死锁的检测及解除:允许进程发生死锁,通过系统的检测及时地检测出死锁的发生,然后采取某种措施解除死锁。
      • 死锁的几种处理策略的比较
        • 比较

    • 2.4.3 死锁预防 死锁预防的发生只需要破坏死锁产生的四个必要条件之一即可。
      • 1. 破坏互斥条件
      • 2. 破坏不剥夺条件
      • 3. 破坏请求并保持条件
      • 4. 破坏循环等待条件
      • 死锁预防的几种方法的比较

    • 2.4.4 死锁避免
      • 1. 系统安全状态
        • 所谓安全状态,就是找到一个安全序列能够满足每个进程对自由的最大需求,使每个进程可顺利完成。如果无法找到安全序列,则称系统处于不安全状态。
        • 实例

        (1)在T0时刻系统是安全的。因为存在安全序列P2,P1,P3。 ①当前可用磁带机为3台,把这3台分配给P2以满足最大需求,P2结束并归还资源后,系统有5台磁带机可用;​ ②接下来将5台磁带机分配给P1使用以满足最大需求,P1结束并归还资源后,系统有10台磁带机可用; ③最后分配7台给P3使用,P3也能顺利完成。​(2)若在T0时刻后系统分配1台磁带机给P3,系统剩余资源为2,此时系统进入不安全状态,因为找不到安全序列。​ ①把剩下的2台磁带机分配给P2,这样P2完成后只能释放4台磁带机,既不能满足P1又不能满足P3,彼此都在等待对方资源,陷入死锁。

        • 并非所有的不安全状态都是死锁状态,但当系统进入不安全状态后,可能进入死锁状态;反之,只要系统处于安全状态,系统便可避免进入死锁状态。
      • 2. 银行家家算法 银行家算法是最著名的死锁避免算法。银行家算法:次啊用预分配策略检查分配完成时系统是否处于安全状态。​
        • (1)数据结构描述
        • 可利用资源向量Available:代表可用资源,即待分配的资源。
        • 最大需求矩阵Max:代表每个进程对某类资源的最大需求。
        • 分配矩阵Allocation:定义系统中已经分配的资源数。
        • 需求矩阵Need:代表每个进程接下来还需要多少资源。Need=Max-Allocation。
        • (2)银行家算法描述
        • 看看就行,具体看题
        • (3)安全性算法
        • 看看就行,具体看题

      • 3. 安全性算法举例 详见课本。
      • 4. 银行家算法举例 详见课本。
    • 2.4.5 死锁检测和解除 检测死锁:利用死锁定理化简资源分配图以检测死锁的存在。
      • 1. 资源分配图
        • 系统死锁可用资源分配图来描述。
        • 圆圈代表一个进程;
        • 框代表一类资源;
        • 框中的一个圆代表一类资源中的一个资源;
        • 从进程到资源的有向边称为请求边,表示该进程申请一个单位的该类资源;
        • 从资源到进程的边称为分配边,表示该类资源已有一个资源分配给了该进程。
        • 如图所示

      • 2. 死锁定理
        • 系统状态S为死锁的条件是当前仅当S状态的资源分配图是不可完全简化的,该条件为死锁定理。
      • 3. 死锁解除
        • (1)资源剥夺法:挂起某些死锁进程并抢夺它的资源,以便让其他进程继续推进。
        • (2)撤销进程法:强制撤销部分,甚至全部死锁进程并剥夺这些进程的资源。
        • (3)进程回退法:让一个或多个进程回退到足以回避死锁的地步。
    • 2.4.0 题目补充
      • (1)出现了循环等待的现象,意味着可能会导致死锁。进程释放资源不会导致死锁,进程自己进入死循环只能产生“饥饿”,不涉及其他进程。共享型设备允许多个进程申请使用,因此不会造成死锁。死锁一定要两个或两个以上的进程才会导致,而饥饿可能由一个进程导致。
      • (2)系统产生死锁的可能原因是独占资源分配不当。
      • (3)多道程序技术要求进程间能实现并发,需要实现进程调度以保证CPU的工作效率,而并发性的实现需要中断功能的支持。
      • (4)三个进程共享四个同类资源,这些资源的分配与释放只能一次一个,已知每个进程最多需要两个该类资源,则该系统进程请求该类资源必然能得到,不会发生死锁。因为每个进程都分得一个资源时,还有一个资源可用让任意一个进程满足,这样这个进程可用顺利运行完成而释放它的资源。
      • (5)资源分配图是一个有向图,用于表示某时刻系统资源与进程之间的关系。
      • (6)死锁的四个必要条件中,无法破坏的是互斥使用资源。
      • (7)死锁与不安全状态的关系:不是所有的不安全状态都是死锁状态,当系统进入不安全状态后,便可能进入死锁状态;反之,只要系统处于安全状态,系统便可避免进入死锁状态;死锁状态必定是不安全状态。
        • 关系图表

      • (8)死锁检测一般采用两种方法:资源有向图法和资源矩阵法。前驱图只是说明进程之间的同步关系,搜索树用于数据结构的分析,安全图并不存在。注意死锁避免和死锁检测的区别:死锁避免是指避免死锁发生,即死锁没有发生;死锁检测是指死锁已出现,要把它检测出来。
      • (9)某个进程主动释放资源不会导致死锁,因为破坏了请求并保持条件;回退是指从此时此刻的状态退回到一分钟之前的状态,假如一分钟之前拥有资源X,它有可能释放了资源X,那就不称回到一分钟之前的状态,也就不是回退;由于进程过于“慷概”,不断把自己已得到的资源送给必然,导致自己长期无法完成,所以是饥饿。
      • (10)出现了环路,只是满足了循环等待的必要条件,而满足必要条件不一定导致死锁,也就是说出现了环路不能判断是否处于死锁状态;没有环路,破坏了循环等待条件,一定不会发生死锁;每种资源只有一个,又出现了环路,这是死锁的充分必要条件,可用确定是否有死锁;即使每个进程至少有一条请求边,若资源足够,则不会发生死锁,但若资源不足,则有可能发生死锁。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值