第一部分 教材习题(P84)
1、什么是前趋图?为什么要引入前趋图?
前趋图:是用于描述程序段或进程之间执行的先后顺序的有向无循环图。
引入的原因:为了更好的描述程序的顺序和并发执行的情况。
试画出下面4条语句的前趋图:
S1:a:=x+y;
S2:b:=z+1;
S3: c:=a-b;
S4: w:=c+1;
【解】前趋图如下:
3、为什么程序并发执行会产生间断性特征?(P36)
程序在并发执行时,程序之间是共享系统资源的,但是往往资源的数目少于进程的数目,就会存在资源抢占的问题.当一个共享的资源被占用时,其它需要同个资源的程序必须暂停,而等待资源的释放才可继续运行。故程序在cpu上运行时会出现断断续续的特征。
例如: 打印机是一个共享的资源,当一个程序使用了打印机进行打印时,于此同时另一个程序也申请打印机的打印服务,由于被占用,故需等待打印机释放,这期间程序就会出现断断续续。
4、程序并发执行,为何会失去封闭性和可再现性?(P37)
程序在并发执行时,是多个程序共享系统中的各种资源,因而这些资源的状态将由多个程序来改变,致使程序的运行已失去了封闭性。同时由于失去了封闭性,也将导致其再失去可再现性。程序在并发执行时,由于失去了封闭性,程序经过多次执行后,其计算机结果已与并发程序的执行速度有关,从而使程序的执行失去了可再现性。
5、在操作系统中为什么要引入进程概念?(P37)它会产生什么样的影响?
在操作系统中引入进程的概念,是为了实现多个程序的并发执行。传统的程序不能与其他程序并发执行,只有在为之创建进程后,才能与其他程序(进程)并发执行。这是因为并发执行的程序(即进程)是“停停走走”地执行,只有在为它创建进程后,在它停下时,方能将其现场信息保存在它的PCB中,待下次被调度执行是,再从PCB中恢复CPU现场并继续执行,而传统的程序却无法满足上述要求。
建立进程所带来的好处是使多个程序能并发执行,这极大地提高了资源利用率和系统吞吐量。但管理进程也需付出一定的代价,包括进程控制块及协调各运行机构所占用的内存空间开销,以及为进行进程间的切换、同步及通信等所付出的时间开销。
6、试从动态性、并发性和独立性上比较进程和程序?(P37)【解】
(1)动态性:进程既然是进程实体的执行过程,因此,动态性是进程最基本的特性。动态性还表现为:“它由创建而产生,由调度而执行,因得不到资源而暂停执行,以及由撤消而消亡”。可见,进程具有一定的生命周期。而程序只是一组有序指令的集合,并存放在某种介质上,本身并无运动的含义,因此,程序是个静态实体。
(2)并发性:所谓进程的并发,指的是多个进程实体,同存于内存中,能在一段时间内同时运行。并发性是进程的重要特征,同时也成为OS的重要特征。引入进程的目的也正是为了使其程序能和其他进程的程序并发执行,而程序是无法并发执行的。
(3)独立性:进程实体是一个能独立运行的基本单位,也是系统中独立获得资源和独立调度的基本单位。凡未建立进程的程序,都不能作为一个独立的单位参加运行。
7、试说明PCB的作用?为什么说PCB是进程存在的惟一标志?(P41)
PCB是进程实体的一部分,是OS中最重要的记录型数据结构。它记录了OS所需的、用于描述进程情况及控制进程运行所需的全部信息。PCB的作用,是使一个在多道程序环境下不能独立运行的程序(含数据)成为一个能独立运行的基本单位,一个能与其他进程并发执行的进程。或者说,OS是根据PCB来对并发执行的进程进行控制和管理的。
在进程的整个生命周期中,系统总是通过PCB对进程进行控制,也就是说,系统是根据进程的PCB感知到该进程的存在的,所以说,PCB是进程存在的标志。
8、PCB提供了进程管理和进程调度所需要的哪些信息?
1:进程标识符,用于唯一地标识一个进程,
通常有外部标识符(方便用户进程的访问)和内部标识符(方便系统对进程的访问)
2:处理机状态信息,也就是处理机的上下文,(处理机执行和进程切换时需要用到上下文)主要是由处理机各种寄存器中的内容组成的,如:通用寄存器(用于暂存信息)、指令计数器(PC寄存器,存放下一条指令的地址)、程序状态字PSW(含有条件码,执行方式,中断屏蔽码等状态信息)、用户栈指针(指向存放过程和系统调用参数及调用地址的栈的栈顶),
3:进程控制信息:用于进程控制所需要的信息。
①程序和数据的地址,进程实体中的程序和数据的内存或外存地址
②进程同步和通信机制,如消息队列指针、信号量等,
这个是实现进程同步和进程通信时的必需机制。
③资源清单,该清单中列出了进程在运行期间所需的全部资源(除CPU
以外),另外还有一张已分配到该进程的资源的清单
④衔接指针,给出了本进程(PCB)所在队列中
的下一个进程的PCB的首地址
4:进程调度信息:用于进程调度所需要的信息,可以了解进程的状态和进程调度信息。
① 进程状态,指明进程的当前状态,是作为进程调度和对换时的依据
②进程优先级,使用与描述进程使用处理机的优先级别的一个整数,优
先级高的进程应优先获得处理机
③进程调度所需的其他信息,与所采用的进程调度算法有关
④事件,进程由执行状态转变为阻塞状态所等待发生的事件,即阻塞原因。
9、进程控制块的组织方式有哪几种?
1:线性方式,即将系统中所有的PCB都组织在一张线性表中,该表的首址存放在内存
的一个专用区域中。可根据表的首地址和索引实现访问,由于每次查找需要查找
整个表,故主要适用于系统中的进程数目不多的情形下。
2:衔接方式,把具有相同状态进程的PCB分别通过PCB中的衔接指针链接成一个队列
形成若干不同状态的队列,便可以根据进程的状态选取特定状态队列进行访问存取。
3:索引方式,系统根据所有进程状态的不同,建立几张索引表,各个索引表在内
存的首地址记录在内存的一些专用单元之中, 用添加索引表的方式记录具有相应状态下的某个PCB在PCB表中的地址。通过索引表的地址内容间接找到PCB。
10、何谓操作系统内核?内核的主要功能是什么?
操作系统内核:
将一些与硬件紧密相关的模块(如中断处理程序等)、各种常用设备的驱动程序以
及运行频率较高的模块,都安排在紧靠硬件的软件层次中,并将它们常驻内存,即所谓的操作系统内核(OS内核)。
其主要功能有:1:支撑功能:
a、中断处理管理;如:系统调用,键盘命令输入,进程调度等所引发的中断。
b、时钟管理;如:时间片轮转调度算法中,一个时间片用完便会产生一个中断信号。
c、原语操作实现; 如:原子操作过程中的动作不允许被中断。
2:资源管理功能:
a、进程管理;如:进程的调度与创建和撤销等。
b、存储器管理;如:用于地址映射的地址转换机构,内存分配保护和内存对换的功能模块。
c、设备管理功能;如:设备的驱动程序,缓解I/O矛盾的缓冲管理,实现设备独立性的模块
11、试说明进程在三个基本状态之间转换的典型原因?(P38)
(1)处于就绪状态的进程,当进程调度程序为之分配了处理机后,该进程就由就绪状态变为执行状态。
(2)正在执行的进程因发生某事件而无法执行,如暂时无法取得所需资源,则由执行状态转变为阻塞状态。
(3)正在执行的进程,如因时间片用完或被高优先级的进程抢占处理机而被暂停执行,该进程便由执行状态转变为就绪状态。
12、为什么要引入挂起状态?(P39)该状态有哪些性质?
(1)终端用户的请求:当终端用户在自己的程序运行期间发现有可疑问题时,希望暂时使自己的程序静止下来。
(2)父进程请求:父进程希望挂起自己的某个子进程,以便考查和修改该子进程,或者协调各子进程间的活动。
(3)负荷调节的需要:当实时系统中的工作负荷较重,已可能影响到对实时任务的控制时,可由系统把一些不重要的进程挂起,以便系统能正常运行。
(4)操作系统的需要:OS有时希望挂起某些进程,以便检查运行中的资源使用情况或进行记账。
13、在进行进程切换时,所要保存的处理机状态信息有哪些?(P42)
保存的处理机状态信息主要由处理机中的各种寄存器内容组成。这些寄存器包括:通用寄存器,指令寄存器,程序状态字PSW,用户栈指针。
14、试说明引起进程创建的主要事件。(P44)
(1)用户登录 在分时系统中,用户在终端键入登录命令后,若是合法用户,系统将为该终端用户建立一个进程,并插入到就绪队列中。
(2)作业调度 批处理程序中,作业调度程序按一定的算法调度到某个作业时,就将该作业装入内存,为它分配必要的资源,并立即为其创建进程,插入到就绪队列中。
(3)提供服务 运行中的用户程序提出某种请求,系统专门创建一个进程来提供用户所需服务。
(4)应用请求 应用进程自己创建一个进程,使自己和新进程以并发运行方式完成特定任务。
15、试说明引起进程被撤消的主要事件。
引起进程被撤销的主要事件有:
1: 进程的正常结束 2: 进程的异常结束(如程序访问越界、以不适当方式读取文件、把数据当指令从而执行不存在的指令、执行没有权限的指令、进程执行超时、进程等待超时、执行禁止的计算、I/O设备故障等)
3: 外界干预,进程应外界的请求而终止(如操作系统干预、父进程请求、父进程终止等)
16、在创建一个进程时所要完成的主要工作是什么?(P44)
需完成的主要工作有:
(1)申请空白PCB;
(2)为新进程分配资源;
(3)初始化PCB,其中包括:
初始化标识符信息。将系统分配的标识符、父进程标识符填入新PCB中;
初始化处理机状态信息。使程序计数器指向程序入口地址,使栈指针指向栈顶;
初始化处理机控制信息。将进程状态设置为就绪或静止就绪,对于优先级通常设置为最低,除非用户提出高优先级要求。
(4)将新进程插入就绪队列。
17、在撤消一个进程时所要完成的主要工作是什么?
系统发现要求终止进程的事件请求,OS开始调用进程终止原语来终止进程。
其中 进程终止原语的主要工作如下:
1:判断终止进程的标识符从而检索提取出特定进程的PCB,从中读取进程状态信息。
2:根据进程不同的状态信息,执行不同的处理操作。
3:判断进程有无子孙进程,有则将其终止,防止其成为不可控的进程。
4:归还被终止进程的所有资源给操作系统或者其父进程。
5:将被终止进程从其所在执行队列移除,并等待其它程序来搜集信息。
18、试说明引起进程阻塞或被唤醒的主要事件是什么?(P46)
1:由于系统无足够的资源,向系统请求资源分配失败时,进程不能继续运行而变为阻塞状态
如:已经有一个进程在使用打印机资源,而另一进程也要申请使用打印机资源,由于只有一台打印机,这一进程将被阻塞,必须等待资源释放才能被唤醒而继续运行。
2:等待进程某种操作的完成。
如:进程启动了I/O操作,只有在进程完成了I/O操作后该进程才能继续运行,
那么在等待I/O完成这段时间,进程将处于阻塞状态。
3:新数据还未到达,进程无法继续运行。
如:一个进程需要等待另一数据的到达才能继续进行,而数据未到达,那么在等待的这段时间内进程将处于阻塞状态。
4:进程等待新任务的到达。
如:在网络环境下下的发送数据包进程,若已有的数据包任务都已发送完毕而无数据包可发的情况下,发送进程将处于阻塞状态;需等待新任务的到达而被重新唤醒而继续运行。
19、为什么要在OS中引入线程?(P72)
为了减少程序在并发执行时所付出的时空开销,使OS具有更好的并发性。进程的两个基本属性:(1)进程是一个可拥有资源的独立单位;(2)进程同时又是一个可独立调度和分派的基本单位。将进程的上述两个属性分开,由OS分开处理,亦即对于作为调度和分派的基本单位,不同时作为拥有资源的单位;而对于拥有资源的基本单位,又不对之进行频繁的切换。正是在这种思想的指导下,形成了线程的概念。
20、明线程具有哪些属性?(P73)
1: 线程是轻型进程,线程中的实体基本上不拥有系统资源,只是有一点必不可少的、能保证独立运行的资源,即一个用于控制线程运行的线程控制块TCB,用于指示被执行指令序列的程序计数器、保留局部信息的一组寄存器和堆栈。
2:在引入线程的OS中,线程是独立调度和分派的基本单位,能独立运行。时空开销小。
当在同一进程中,线程的切换不会引起进程的切换。
当在不同进程中的线程互相切换,则必然会引起进程的切换。
3:在引入线程的OS中,不仅进程之间可以并发执行,而且在一个进程中的多个线程之间也可以并发执行,从而显著地提高了程序的并发执行程度。
4:线程除了拥有自己的少量资源外,一个进程的多个线程之间共享该进程所拥有的资源,故同一进程的所有线程都具有相同的地址空间并且还可以访问进程所拥有的资源,如已打开的文件和它所申请到的I/O设备等,但同时带来的缺点就是同一个进程中的不同线程之间的独立性比不同进程之间的独立性低得多。
21、试从调度性、并发性、拥有资源及系统开销几个方面,对进程和线程进行比较。
(1)调度性 在传统的OS中,拥有资源的基本单位和独立调度、分派的基本单位都是进程。而在引入线程的OS中,则把线程作为调度和分派的基本单位,而把进程作为资源拥有的基本单位,使传统进程的两个属性分开,线程便能轻装运行,从而显著提高系统并发程度。在同一进程中,线程的切换不会引起进程切换,在由一个进程中的线程切换到另一个进程中的线程时,将会引起进程切换。
(2)并发性 多线程的操作系统中,不仅进程可以并发执行,而且一个进程的多个线程也可并发执行。从而能更有效地使用系统资源和提高系统吞吐量。
(3)拥有资源 进程是拥有资源的独立单位。线程自己基本不拥有系统资源,但可访问隶属进程的资源。
(4)系统开销 在创建和撤消进程时,系统要为之分配或回收资源,所以系统开销要显著大于在创建和撤消线程的开销。在进行进程切换时,涉及到整个当前进程CPU环境的保存以及新被调度运行的进程的CPU环境的设置。而线程切换只须保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。可见,进程切换的开销也远大于线程切换的开销。此外,由于同一进程中的多个线程具有相同的地址空间,致使它们之间的同步和通信的实现也变得比较容易。
22、线程控制块TCB中包含了哪些内容?
1:线程标识符。用来赋予每一个线程一个唯一的标识符。
2:寄存器,包括用于存储下一条指令地址的程序计数器PC, 存储状态的状态寄存器,
以及通用功能的通用寄存器。
3:线程运行状态。用于描述线程正处于何种运行状态。
4:优先级。用于描述线程执行的优先级。
5:线程专有存储区。用于线程切换时存放现场信息和线程的统计信息。
6:信号屏蔽。用来对某些信号加以屏蔽。
7:堆栈指针。为每个线程设置一个堆栈,用于将每次过程调用中使用的局部变量和返回地址保存起来。在TCB中也需设置两个指向堆栈的指针。当线程运行在用户态时,使用用户自己的用户栈来保存局部变量和返回地址;当线程运行在核心态时,使用系统的核心栈来保存局部变量和返回地址。
23、何为用户级线程和内核支持线程?(P77)
用户级线程仅存在于用户级中,它的创建、撤消和切换都不利用系统调用实现,与内核无关,相应的,内核也不知道有用户级线程存在。
内核级线程依赖于内核,无论用户进程中的线程还是系统进程中的线程,其创建、撤消、切换都由内核实现。在内核中保留了一张线程控制块,内核根据控制块感知线程的存在并对其进行控制。
比较:
(1)线程的调度与切换速度 内核支持线程的调度和切换与进程的调度和切换十分相似。例如,在线程调度时的调度方式,同样也是抢占方式和非抢占方式两种。在线程的调度算法上,也同样可采用时间片轮转、优先权算法等。当由线程调度选中一个线程后,再将处理机分配给它。当然,线程在调度和切换上所花费的开销要比进程的小得多。对于用户级线程的切换,通常是发生在一个应用程序的多线程之间,这时,不仅无须通过中断进入OS的内核,而且切换的规则也远比进程调度和切换的规则简单。例如,当一个线程阻塞后会自动切换到下一个具有相同功能的线程,因此,用户级线程的切换速度特别快。
(2)系统调用 当传统的用户进程调用一个系统调用时,要由用户态转入核心态,用户进程将被阻塞。当内核完成系统调用而返回时,才将该进程唤醒,继续执行。而在用户级线程调用一个系统调用时,由于内核并不知道有该用户级线程的存在,因而把系统调用看作是整个进程的行为,于是使该进程等待,而调度另一个进程执行,同样是在内核完成系统调用而返回时,进程才能继续执行。如果系统中设置的是内核支持线程,则调度是以线程为单位。当一个线程调用一个系统调用时,内核把系统调用只看作是该线程的行为,因而阻塞该线程,于是可以再调度该进程中的其他线程执行。
(3)线程执行时间 对于只设置了用户级线程的系统,调度是以进程为单位进行的。在采用轮转调度算法时,各个进程轮流执行一个时间片,这对诸进程而言,似是公平。但假如在进程A中包含了一个用户级线程,而进程B中含有100个线程,这样,进程A中线程的运行时间,将是进程B中各线程运行时间的100倍;相应地,速度就快100倍。假如系统中设置的是内核支持线程,其调度是以线程为单位进行的,这样,进程B可以获得的CPU时间是进程A的100倍,进程B可使100个系统调用并发工作。
24、试说明用户级线程的实现方法。(P77)
用户级线程也需要 间接的 取得内核的支持,故用户级线程运行在一个 ”中间系统” 上来间接取得内核的支持。其是在用户空间实现的,并且所有用户级线程具有相同的结构。
而实现中间系统的方式有两种。
1:运行时系统(Runtime System)方式。
其实质上是用于管理和控制线程的函数的集合,包括了各种对线程操作,同步和通信的 函数,而有了这些函数,才能使用户级线程与内核无关。
在传统的OS中,进程的切换需要先由cpu的用户态转为cpu的核心态,然后由核心即 内核执行切换的任务。
而运行时系统中的所有函数驻留在用户空间,它是作为用户级线程与内核之间的接口。
其不需要转入cpu的核心态,而是由运行时系统的函数来执行切换任务。其无需转入内核,故切换速度将非常快。
2: 内核控制线程方式。(组合方式)
内核控制线程又叫做轻型线程LWP(Light Weight Process),每个进程可拥有多个LWP.
LWP可通过系统调用来取得内核提供的服务.这样的话,当一个用户级线程运行时,只要将它连接到一个LWP上,其便具有了内核支持线程的所有属性,即间接获得了内核的支持。
用户级线程能访问利用LWP访问内核并与内核通信,但内核缺只能看到LWP而看不到用户级线程.故也就是LWP实现了内核与用户级线程的隔离,使用户级线程与内核无关。
25、试说明内核支持线程的实现方法。(P77)
系统在创建一个新进程时,会为它分配一个任务数据区,数据区是若干个TCB空间的大小。
在每一个TCB中可保存线程标识符,优先级,线程运行的cpu状态等信息,填充完信息的PCB被保存在内核空间中。
内核支持线程的创建和撤销过程:
每当进程要创建一个线程时,就为新进程分配一个TCB,并将有关信息填入其中,再为其分配必要的资源,必要的资源可以是指分配若干字节的栈空间和局部存储区。于是新创建的线程便可以准备被调度而执行。而如果任务数据区的TCB被分配完了,而进程又需要创建新的线程,此时只要已创建的线程数目不超过系统的允许值,系统可以再为其分配新的TCB空间。而当线程要撤销时,需要回收该线程的所有资源和TCB。
故内核支持线程的创建和撤销与进程的创建和撤销是类似的。
26、多线程模型有哪几种类型?多对一模型有何优缺点?
多对一模型、一对一模型和多对多模型。
多对一模型即将多个用户线程映射到一个内核控制线程。
其中多个用户线程一般隶属于一个进程,运行在该进程的用户空间。仅当进程需要访问内核时,才将其映射到一个内核控制线程(LWP)上,且只有一个线程访问内核。
多对一模型的优点在于线程管理的开销小,效率高,缺点在于,如果一个线程在访问内核时发生阻塞,则整个进程都会被阻塞;此外,在任一时刻,只有一个线程能够访问内核,多个线程不能同时在多个处理机上运行。
第二部分问答题
1、进程在运行时,存在哪两种形式的制约?并举例说明之。
(1)间接相互制约关系。举例:有两进程A 和B,如果A 提出打印请求,系统已把唯一的一台打印机分配给了进程B,则进程A 只能阻塞;一旦B 释放打印机,A 才由阻塞改为就绪。
(2)直接相互制约关系。举例:有输入进程A 通过单缓冲向进程B 提供数据。当缓冲空时,计算进程因不能获得所需数据而阻塞,当进程A 把数据输入缓冲区后,便唤醒进程B;反之,当缓冲区已满时,进程A 因没有缓冲区放数据而阻塞,进程B 将缓冲区数据取走后便唤醒A。
2、为什么进程在进入临界区之前,应先执行“进入区”代码,在退出临界区后又执行“退出区”代码?(P50)
为了保证诸进程互斥进入自己的临界区,便可实现它们对临界资源的互斥访问。为此,每个进程在进入临界区之前应先对欲访问的临界资源进行检查,看它是否正被访问。如果此刻临界资源没被访问,则该进程便可进入临界区,对该资源进行访问,并设置它正被访问的标志;如果此刻该临界资源正被某进程访问,则本进程不能进入临界区。因此,必须在临界区前增加一段用于上述检查的代码,把这段代码称为进入区。相应地,在临界区后面也要加上一段称为退出区的代码,用于将临界区正被访问的标志恢复为未被访问标志。
3、同步机构应遵循哪些基本准则?为什么?(P50)
同步机构应遵循的基本准则有:
(1)空闲让进
无进程处于临界区时,相应的临界资源处于空闲状态,因而可允许一个请求进入临界区的进程立即进入自己的临界区,以有效利用临界资源。
(2)忙则等待
当已有进程进入自己的临界区时,意味着相应的临界资源正被访问,因而所有其他试图进入临界区的进程必须等待,以保证诸进程互斥地访问临界资源。
(3)有限等待
对要求访问临界资源的进程,应保证该进程能在有限时间内进入自己的临界区,以免陷入“死等”状态。
(4)让权等待
当进程不能进入自己的临界区时,应立即释放处理机,以免进程陷入“忙等”。
4、试从物理概念上来说明记录型信号量wait和signal操作?(P51)
在记录型信号量机制中,S.value的初值表示系统中某类资源的数目,因而又称资源信号量,每次的wait操作,意味着进程请求一个单位的资源,因此描述为S.value:=S.value-1;当S.value<0时,表示资源已分配完毕,因而进程调用block原语,进行自我阻塞,放弃处理机,并插入到信号量链表S.L中。可见,该机制遵循了让权等待准则。此时S.value的绝对值表示在该信号量链表中已阻塞进程的数目。每次signal操作,表示执行进程释放一个单位资源,故S.value:=S.value+1操作表示资源数目加1。若加1后仍是S.value<=0则表示该信号量链表中,仍有等待该资源的进程被阻塞,故还要调用wakeup原语,将S.L链表中的第一个等待进程唤醒。如果S.value的初值为1,表示只允许一个进程访问临界资源,此时的信号量转化为互斥信号量。
5、你认为整型信号量机制是否完全遵循了同步机构的四条准则?(P52)
在整型信号量机制中的wait操作,只要是信号量S<=0,就会不断地测试,因此,该机制并未遵循“让权等待”的准则,而是使该进程处于“忙等”的状态。
6、如何利用信号量机制来实现多个进程对临界资源的互斥访问?并举例说明之。
为使多个进程互斥访问某临界资源,只需为该资源设置一互斥信号量mutex,并设其初值为1,然后将各进程访问该资源的临界区CS置于wait和signal操作之间即可.这样,每个欲访问该临界资源的进程在进入临界区之前,都要先对mutex 执行wait 操作,若该资源此刻未被访问,本次wait 操作必然成功,进程便可进入自己的临界区,这时若再有其他进程也欲进入自己的临界区,此时由于对mutex 执行wait操作定会失败,因而该进程阻塞,从而保证了该临界资源能被互斥访问.当访问临界资源的进程退出临界区后,应对mutex执行signal 操作,释放该临界资源.利用信号量实现进程互斥的进程描述如下:
Var mutex: semaphore:=1;
begin
parbegin
process 1: begin
repeat
wait;
critical section
signal;
remainder section
until false;
end
process 2: begin
repeat
wait;
critical section
signal;
remainder section
until false;
end
parend
7、试写出相应的程序来描述图2-17所示的前趋图。
Var a,b,c,d,e,f,g,h; semaphore:=0,0,0,0,0,0,0,0;
begin
parbegin
begin S1;signal(a);signal(b);end;
begin wait(a);S2;signal(c);signal(d);end;
begin wait(b);S3;signal(e); end;
begin wait(c);S4;signal(f);end;
begin wait(d);S5;signal(g);end;
begin wait(e);S6;singal(h);end;
begin wait(f);wait(g); wait(h); S7;end;
parend
end
(2)
Var a,b,c,d,e,f,g,h,i,j; semaphore:=0,0,0,0,0,0,0,0,0,0,0;
begin
parbegin
begin S1;signal(a);signal(b);end;
begin wait(a);S2;signal(c);signal(d);end;
begin wait(b);S3;signal(e);signal(f);end;
begin wait(c);S4;signal(g);end;
begin wait(d);S5;signal(h);end;
begin wait(e);S6;singal(i);end;
begin wait(f);S7;signal(j);end;
begin wait(g); wait(h);wait(i);wait(j); S8;end;
parend
end
在生产者—消费者问题中,如果缺少了signal(full)或 signal(empty),对执行结果会有什么影响?
【解】在生产者—消费者问题中,如果缺少了signal(full) ,那么消费者会认为生产者没有生产而阻塞,而生产者会不断生产,直到empty为0后阻塞,然后两个进程陷入“死等”状态。
如果缺少了signal(empty)开始两进程可同步运行。但当empty为0 时生产者会因此而阻塞,然后消费者进程继续运行直到full也为0阻塞,然后两个进程陷入“死等”状态。
在生产者—消费者问题中,如果将两个wait操作即wait(full)和wait(mutex)互换位置,或者将signal(mutex)与signal(full)互换位置,结果会如何?
【解】如果将wait(full)和wait(mutex)互换位置,则如果consumer先进入临界区,就会一直等待full,但由于没有signal(mutex) ,producer将无法进入临界区而等待,则两个进程相互等待,陷入死锁。
如果signal(full)与signal (mutex)互换位置,则会使full的值不再是等待的consumer进程数目。
var mutex,empty,full:semaphore:=1,n,0;
buffer:array[0,…,n-1]of item; in,out:integer:=0,0;
Begin
parbegin
producer:
begin
repeat
……
producer an item in nextp;
……
wait(mutex);//前2句颠倒则死锁
wait(empty);
buffer(in):=nextp;
in:=(in+1)mod n;
signal(full); //后2句颠倒不死锁
signal(mutex);
until false;
end
consumer:
begin
repeat
wait(full);
wait(mutex);
nextc:=buffer(out);
out:=(out+1)mod n;
signal(mutex);
signal(empty);
consume the item in nextc;
until false;
end
Parend
end
由于V操作是释放资源,因此对调V操作的次序无关紧要。
而对调P操作的次序则可能导致死锁。
这时因为对调P操作后,有可能出现这样一种特殊情况:在某一时刻缓冲池中已装满了产品且缓冲池中无进程工作(这时信号量full的值为n,信号量empty的值为0,信号量mutex的值为1),若系统此时调度生产者进程运行,生产者进程又生产了一个产品,它执行P(mutex)并顺利进入临界区(这时mutex值为0),随后它执行p(empty)时因没有空闲缓冲区而受阻等待,等待消费者进程进入缓冲池取走产品以释放出缓冲区;
消费者进程执行p(full)后再执行p(mutex)时,因缓冲池被生产者进程占据而无法进入。
这样就形成了生产者进程在占有临界资源的情况下,等待消费者进程取走产品,而消费者进程又无法进入临界区取走产品的僵局,此时两进程陷入死锁。
- 我们为某临界资源设置一把锁W,当W=1时表示关锁;当W=0时表示锁已打开。试写出开锁和关锁原语,并利用它们去实现互斥。
【解】我们采用一个变量W作为“锁”,代表某个临界资源的状态,W=0(false,锁已打开)表示该资源未用,W=1(true,关锁)表示该资源正被使用。同时,用一段程序作为开锁原语,用另一段程序作为关锁原语,要进入临界区的进程首先要执行关锁原语,当它退出临界区时,要执行开锁原语。从而实现对临界区的互斥控制。两个原语的作用是:
加锁原语lock
测试W是否为0
若W=0,让W=1
若W=1,继续测试
开锁原语unlock
使W=0
可见,加锁原语首先要判断临界区中有无进程,若W=0,表示无进程进入临界区,它可以马上进入,并立即将W置为1,同时禁止其他进程进入。若W=1,表示已经有进程进入,它只得等待。这种机构简单方便,但存在CPU的时间浪费,因为等待进入临界区的进程将不断循环测试W,等待W变为0。
- 试修改下面生产者-消费者问题解法中的错误:
producer:
begin
repeat
…
produce an item in nextp;
wait(mutex);
wait(full);
buffer(in):=nextp;
signal(mutex);
until false;
end
consumer:
begin
repeat
wait(mutex);
wait(empty);
nextc:=buffer(out);
out:=out+1;
signal(mutex);
consume item in nextc;
until false;
end
修改为:
producer:
begin
repeat
produce an item in nextp;
wait (empty);
wait (mutex);
buffer (in): =nextp;
in:=(in+1) mod n;
signal (mutex);
signal (full)
until false;
end
consumer:
begin
repeat
wait (full);
wait(mutex);
nextc:=buffer(out);
out:=(out+1) mod n;
out:=out+1;
signal(mutex);
signal(empty);
consume item in nextc;
until false
end
- 试利用记录型信号量机制写出一个不会出现死锁的哲学家进餐问题的算法。
在测量控制系统中的数据采集任务时,把所采集的数据送往一单缓冲区;计算任务从该单缓冲区中取出数据进行计算。试写出利用信号量机制实现两任务共享单缓冲区的同步算法。
Var mutex, empty, full: semaphore: =1,1,0;
buffer: item;
begin
parbegin
Receive:
begin
repeat
Wait(empty);
Wait(mutex);
buffer: =nextp;
Signal(mutex);
Signal(full);
until false
end
Get:
begin
repeat
Wait (full);
Wait (mutex);
nextp: =buffer;
Signal (mutex);
Signal (empty);
until false
end
parend
end
- 画图说明管程由哪几部分组成?(P56)为什么要引入条件变量?(P57)
- 如何利用管程来解决生产者—消费者问题?(P60)
Type producer-consumer=monitor
var in, out, count: integer;
buffer: array[0,-----,n-1] of item;
notfull,notempty:condition;
procedure entry put(item)
begin
if count>=n then notfull.wait;
buffer(in):=nextp;
in:=(in+1) mod n;
count:=count+1;
if notempty.queue then notempty.signal;
end
procedure entry get(item)
begin
if count<=0 then notempyt.wait;
nextc:=buffer(out);
out:=(out+1) mod n;
count:=count-1;
if notfull.queue then notfull.signal;
end
begin in:=out:=0; count:=0; end
生产者和消费者可描述为:
producer: begin
repeat
produce an item in nextp;
PC.put(item);
until false;
end
consumer: begin
repeat
PC.get(item);
consume the item in nextc
until false;
end
- 什么是AND信号量?试利用AND信号量写出生产者—消费者问题的解法。
【解】AND信号量是指:将进程在整个运行过程中所需的所有临界资源一次性地全部分配给进程,待该进程使用完后再一起释放。只要尚有一个资源未能分配给该进程,其他所有可能为之分配的资源,也不分配给他,即:对若干临界资源分配,采取原子操作方式,要么全部分配到进程,要么一个也不分配。叫AND信号量。
var mutex,empty,full:semaphore:=1,n,0;
buffer: array[0,---,n-1]of item;
in,out:integer:=0,0;
begin
parbegin
producer: begin
repeat
produce an item in nextp
Swait(empty,mutex);
buffer(in):=nextp;
in:=(in+1)mod n;
Ssignal(mutex,full);
until false;
end
consumer: begin
repeat
Swait(full,mutex);
nextc:=buffer(out);
out:=(out+1)mod n;
Ssignal(mutex,empty);
consume the item in nextc;
until false
end;