1、2019/6/13,1,第六章 进程管理,重点:临界区,进程同步与互斥,进程通信,死锁,2019/6/13,2,6.1进程管理的背景,并发进程执行可能是无关的,也可能是交往的。无关的并发进程是指它们分别在不同的变量集合上操作,所以一个进程的执行与其它并发进程的进展无关,即一个并发进程不会改变另一个并发的变量值。然而,交往的并发进程,它们共享某些变量,所以一个进程的执行可能影响其它进程的执行结果 ,产生各种与时间有关的错误。,2019/6/13,3,例1 生产者(producer)和消费者(consumer)问题.生产者将得到的数据放入缓冲区中,而消费者则从同一个缓冲区中取数据消费。缓冲区buf
2、fer为一有界数组,缓冲区中的数据个数用count变量表示,它们均是两个进程的共享变量。,生产者进程: while(count=BUFFER_SIZE) ; /no-op /add an item to the buffer count+; bufferin = item; in=(in+1)% BUFFER_SIZE;,消费者进程: while (count = 0 ) ; /no-op / remove an item from the buffer count-; item = bufferout; out=(out+1)%BUFFER_SIZE;,2019/6/13,4,结果不唯一 (
3、Count=6),Producer中Count+,Consumer中Count-,T0:register1=count;,T1:register1=register1+1;,T4(5):count= register1;,T2:register2=count;,T3:register2=register2-1;,T5(4):count= register2;,( Count=5(7) ),2019/6/13,5,例2 假设有两个并发进程borrow和return分别负责申请与归还主存资源,两个并发进程的程序片段如下所示。X表示现有的空闲主存量,为共享变量,B表示申请或归还的主存量。,proce
4、ss borrow(,B, )int B;if ( BX ) 等待主存资源;X=X-B;修改主存分配表;,process return ( , B,)int B,;X=X+B;释放等待主存资源者;修改主存分配表;,2019/6/13,6,永远等待,process borrow(,B, )int B;if ( BX ) 调度return,Process return(, B, )int B,;X=X+B;释放等待主存资源者;修改主存分配表;, 等待主存资源;X=X-B;修改主存分配表;,2019/6/13,7,6.2 进程互斥,2019/6/13,7,2019/6/13,8,1 临界区 交往的进
5、程会产生错误,其原因在于两个进程交叉访问的共享变量count或X。我们把并发进程中与共享变量有关的程序段称为“临界区”(Critical section) 。一次只允许一个进程使用的资源称临界资源。 为保证临界资源的正确使用,可把临界资源的访问过程分成四个部分: 进入区 临界区 退出区 剩余区 进程中访问临界资源的那段代码称临界区。,621 互斥与临界区,2019/6/13,2019/6/13,9,2019/6/13,9,生产者和消费者两进程中:,生产者进程的临界区:count+;bufferin = item;in = (in+1) % BUFFER_SIZE;,消费者进程的临界区:coun
6、t-;item = bufferout;out = (out+1) % BUFFER_SIZE;,2019/6/13,10,(1)互斥性:如果一个进程在它临界区中执行,其它任何进程均不能进入相关的临界区执行; (2)进展性:如果一个进程不在它临界区中执行,不应阻止其它任何进程进入相关的临界区执行; (3)有限等待性:某个进程从申请进入临界区时开始,应在有限的时间内得以进入临界区执行。,如果能保证一个进程在临界区中执行时,不让另一个进程进入相关的临界区执行,那么就不会造成与时间有关的错误。这种不允许两个以上共享共有资源或变量的进程同时进入临界区执行的性质称为互斥(mutual exclusion
7、),即相关临界区的执行必须具有排它性。 临界区的管理应有三个要求:,2 互斥(mutual exclusion),2019/6/13,11,622 临界区管理的讨论,2019/6/13,12,6221互斥的软件实现方法,1 标志法 如P1和P2两个进程,它们的程序代码均包含有相关的临界区。我们对P1和P2分别用两个变量inside1和inside2来标志它们是否在临界区中,当进程在它的临界区内时其值为1,不在临界区时其值为0。 两并发进程的程序如下:,2019/6/13,13,int inside1, inside2; /*两并发进程共享变量*/ inside1 = 0; /* 表示P1不在临
8、界区内 */ inside2 = 0; /* 表示P2不在临界区内 */ process P1 while (inside2) ; /*等待inside2变成0*/ inside1 = 1; 临界区; inside1 = 0; process P2 while (inside1) ; /*等待inside1变成0*/ inside2 = 2; 临界区; inside2 = 0; ,可能出现两个并发进程同时进入了各自的临界区 的情况,2019/6/13,14,2. 严格轮换法,用一个指针turn来指示应该由哪个进程进入临界区。若turn = 0则表示P0可进入临界区;若turn = 1则表示P1
9、可进入临界区。 进程程序描述如下:,2019/6/13,15,int turn; turn = 0; process P0 while (turn=1) ; /*等待turn变成0*/ 临界区; turn = 1; process P1 while (turn=0) ; /*等待turn变成1*/ 临界区; turn = 0; ,严格强制了两个进程轮换地进入临界区,2019/6/13,16,3. Peterson算法,Peterson算法能正确解决互斥问题。该方法为每一个进程设置一个标志,当标志为1时表示该进程请求进入临界区。另外再设置一个指针turn以指示可以由哪个进程进入临界区,当turn
10、等于i时则可由进程Pi进入临界区。可以提供两个函数来管理临界区,这两个函数为enter_region, leave_region,程序描述如下:,2019/6/13,17,int turn; int flag2=0,0; void enter_region(int process) int other; other = 1-process; flagprocess = 1; turn = other; while (turn = other ,2019/6/13,18,Peterson算法,好处: 能正确解决互斥问题,缺点: 进程会出现“忙等待”,2019/6/13,19,6222互斥的硬件实
11、现方法,1.中断屏蔽方法 思想:使进程进入临界区执行,不响应中断,不切换进程。 屏蔽中断( disable interrupts); 临界区; 开中断( enableinterrupts); 好处:简单。 缺点:系统代价较高;无法在多处理器系统使用。,2.硬件指令方法 1)测试并设置指令TS while (TS( 缺点:同样存在“忙等待”,2019/6/13,20,6.2.3 信号量及P、V原语,信号量荷兰著名的计算机科学家Dijkstra,于1965年提出了一个信号量(semaphore)和P、V操作的同步机构。 其基本原则是在多个相互合作的进程之间使用简单的信号来协调控制。一个进程检测到某
12、个信号后,就被强迫停止在一个特定的地方,直到它收到一个专门的信号为止才能继续执行。这个信号就称为“信号量”。其工作方式有点类似于十字路口的交通控制信号灯 。 信号量被定义为含有整型数据项的结构变量,其整型值大于等于零代表可供并发进程使用的资源实体数,但小于零时则表示正在等待使用临界区的进程数。,2019/6/13,21,信号量数据结构,typedef struct int value;PCB _pointer PCB; semaphore;,2019/6/13,22,P操作原语,原语 :执行时不可中断的过程。 P操作P(s):将信 号量s的整型值减去1,若结果小于0,则将调用P(s)的进程置成
13、等待信号量s的状态。 Void P(semaphore *s) s-value = s-value 1;if ( s-valuePCB); /*将调用进程插入到等待信号量s的进程队列中*/block (CALLER); /*阻塞调用进程*/ ,2019/6/13,23,V操作V(s)原语,V操作V(s):将信号量s的整型值加上1,若结果不大于0,则释放一个等待信号量s的进程。 Void V(semaphore *s) PID proc_id;s-value = s-value + 1;if ( s-valuePCB, /*唤醒该进程*/ ,2019/6/13,24,为进一步理解P、V操作的物理
14、含义,我们可以这样来分析与看待:,P 操作:当信号量s的整型值大于0时,它表示某类公用资源的可用数。因此,每执行一次P操作就意味着请求分配一个单位的该类资源给执行P操作的进程使用,信号量s的整型值应减去1。当信号量s的整型值小于等于0时,表示已经没有此类资源可供分配了,因此,请求资源的进程将被阻塞在相应的信号量s的等待队列中。此时,s的整型值的绝对值等于在该信号量上等待的进程数。 V 操作:执行一次V操作就意味着进程释放出一个单位的该类可用资源,故信号量s的整型值应增加1。若s的整型值还小于等于0,表示在信号量s的等待队列中有因请求该类资源而被阻塞的进程,因此,就把等待队列中的一个进程唤醒,使
15、之转移到就绪队列中去。注意:唤醒的次序依系统而定。,2019/6/13,25,6.2.4 用P、V操作实现进程间的互斥 例如 有两个并发进程insert_item和delet_item分别负责对一个队列进行插入数据项和删除数据项的操作,插入数据项和删除数据项均需要对队列中的指针进行修改。因此,它们对队列中指针的操作是一种互斥关系。定义一个公共的互斥信号量mutex,初值为1。,process insert_item 向系统申请一个缓冲区; 将数据data送入该缓冲区中; P( ,Process delet_item P( 释放数据项data的缓冲区; ,2019/6/13,26,n个进程实现互
16、斥的一般形式,semaphore mutex; mutex.value = 1; process Pi P( ,2019/6/13,27,使用P、V操作实现进程间互斥注意点,当有多个进程在等待进入临界区的队列中排队,而允许一个进程进入临界区时,应先唤醒哪一个进程进入临界区?不应有刻意要求。 在证明使用P、V操作的程序的正确性时,必须证明进程按任意次序进入临界区都不影响程序的正确性。,2019/6/13,28,6. 3 进程同步,2019/6/13,29,631进程同步概念,进程同步的引入:如生产者(producer)和消费者(consumer)两个进程,它们通过一个缓冲区进行生产和消费的协作过
17、程。生产者将得到的数据放入缓冲区中,而消费者则从缓冲区中取数据消费。缓冲区buffer为一有界数组。 有两种情况会导致不正确的结果:一是消费者从一个空的缓冲区buffer中取数据。就意味着重复取已经取走的数据或取缓冲区中并不是生产者放入的数据。另一种情况是生产者把数据存入已满的缓冲区,这就意味着将覆盖尚未消费(取走)的数据。,2019/6/13,30,上述出现的两种不正确的结果是因为它们访问缓冲区的速率不匹配。 正确地控制生产者和消费者的执行,必须使它们在执行速率上做到相匹配,即在执行中它们是应相互制约的。 异步环境下的一组并发进程,因直接制约互相发送消息而进行相互协作、相互等待,使得各进程按
18、一定的速度执行的过程称为进程间的同步。操作系统中实现进程同步的机制称同步机制。迄今,已提出了多种同步机制,本节将介绍两种经典的同步机制:P、V操作和管程。,2019/6/13,31,6.3.2 用P、V操作实现进程间的同步,例1 生产者每次生产一件物品(数据)存入缓冲区,消费者每次从缓冲区取一件物品消费。假定缓冲区只能存放一件物品。生产者进程和消费者进程的程序描述如下:semaphore s1 , s2 ;int B;s1.value = 1 ; s2.value = 0 ;,process producer int data;生产一件物品并暂存在data中;P( ,process consu
19、mer int data;P(消费data;,2019/6/13,32,例2 用pv操作实现:A B,semaphore s1; s1.value = 0 ; process A V( ,2019/6/13,33,例3 用P,V操作实现:,semaphore sa,sb,sc,sd,se,sf; Sa.value=sb.value=sc.value=sd.value=se.value=0; cobegin Pa(); Pb(); Pe(); coend;,AB C D EF,2019/6/13,34,Process Pa V( ,Process PbP(,Process PcP(,Proces
20、s PdP(,2019/6/13,35,Process Pe P( ,Process Pf P( ,2019/6/13,36,int bufferk; semaphore s1, s2, s ; int in, out ; s.value =1 ; s1.value = k ; s2.value = 0 ; in = 0 ; out = 0 ; Cobeginrepeat produceri;repeat consumerj; Coend;,例4 现有m个生产者和n个消费者,它们共享可存放k件物品的缓冲区。这是一个同步与互斥共存的问题。必须使用公用信号量s,以限制它们对缓冲区的互斥存取,另用两
21、个私有信号量s1和s2,以控制生产者不往满的缓冲区中存物品,消费者不从空的缓冲区中取物品。各进程的程序描述如下:,2019/6/13,37,process produceri int item;生产一件物品并暂存 在item中;P(,process consumerj int item;P(消费item;,2019/6/13,38,思考:若把生产者进程的两个P操作使用次序交换一下,即先P(s)后P(s1)结果怎样?,分析:当缓冲区中存满了k件物品时,此时s.value =1 s1.value = 0 , s2.value = k,生产者又生产了一件物品,它欲向缓冲区存放时将在P(&s1)上等待
22、,但它已经占有了使用缓冲区的权利(现在s.value =0)。这时,消费者欲取物品时将由执行P(&s)而被挂起,它得不到存取缓冲区的权利。从而导致生产者等待消费者取走物品,而消费者却在等待生产者释放缓冲区,这种相互等待永远也无法结束,故产生了死锁现象,在用P、V操作实现同步与互斥共存的问题时,应特别小心P操作的次序。一般来说,私有信号量的P操作应在前执行,而用于互斥的公用信号量P操作应在后执行。,2019/6/13,39,例5 有三个并发进程,R负责从输入设备读入信息并传送给M,M将信息加工(空格转为分号)并传送给P,P把加工后的信息打印输出。现有一个缓冲区,容量为K。 用PV操作写出这三个进
23、程正确工作的程序。,semaphore sr,sm,sp; int lr, lm, lp; Datatype BK; Lr=lm=lp=0; sr.value=K ;sm.value=0;sp.value=0; cobegin repeat R; repeat M; repeat P; coend,2019/6/13,40,Process R read data;P(,Process M P(,Process P P(,2019/6/13,41,例6 若零件A的最大库容量为m,零件B的最大库容量为n,当A和B的产量差超过k时,暂停对数量大的零件的生产而补充生产数量少的零件。用p,v操作实现。,
24、Semaphore emptyA,emptyB,fullA,fullB,Sa,Sb; emptyA.value =m;emptyB.value =n;fullA.value =0;fullB.value =0;Sa.value =k;Sb.value =k; cobegin repeat PA; repeat PB; repeat CA; repeat CB; coend,2019/6/13,42,Process PA P( ,Process PB P( ,Process CAP(,2019/6/13,43,例7 读者与写者问题。一个数据集为多个并发进程所共享,其中一些进程只要求读该数据集的内
25、容,这些进程称为“读者”,而另一些进程则要求修改该数据集的内容,这些进程称为“写者”。具体要求是:允许多个读者同时读该数据集的内容,若有一个写者在写,则其他读者不能读,若一个写者在写或有其他读者在读,则其他写者均被拒绝。,int readcount; semaphore mutex , wrt;readcount = 0; mutex.value = 1 ; wrt.value = 1 ; cobegin repeat readeri ; repeat writerj; coend;,2019/6/13,44,process readeri P(,process writerjP(,2019/
26、6/13,45,例8 读者与写者问题。具体要求是:允许多个读者同时读该数据集的内容;若有一个写者在写,则其他读者不能读;若一个写者在写或有其他读者在读,则其他写者均被拒绝;当一个写者正在写,而有多个读者与写者在等待时,写者应优先唤醒。 int readcount, readapp, writecount; semaphore mutex , sw, sr;readcount = 0; writecount = 0; readapp = 0; mutex.value = 1 ; sr.value = 0 ; sw.value = 0 ; cobegin repeat readeri ; repe
27、at writerj; coend;,2019/6/13,46,process readeri P(,2019/6/13,47,process writerjP( ,2019/6/13,48,633 管程,管程的引入: P、V操作来解决同步与互斥问题: 1)P、V操作分散在各进程的程序中,并发程序设计困难。 2)并发程序设计易出错。如,在生产者和消费者问题中,颠倒两个P操作的顺序就会引起死锁。 如果能把有关共享变量的操作集中在一起,就可使并发进程之间的相互作用更为清晰。于是Brinch Hansen 和Hoare提出了一种新的同步机制管程(monitor)。,2019/6/13,49,管程的定
28、义,系统中的共享资源用数据抽象表示,代表共享资源的数据及在其上实施操作的一组过程就构成了管程。 管程是被请求和释放资源的进程所调用。它具有以下基本特性: (1)管程中间的局部数据只能由该管程内的过程存取;(2)一个进程只有通过调用管程内的过程才能进入管程存取共享数据; (3)在任何时刻最多只有一个进程能真正进入管程执行某个内部过程。即进程必须互斥地进入管程调用其内部过程,其它想调用管程内部过程的进程必须等待。,2019/6/13,50,用管程来实现进程间的同步,在管程定义中应增加一些支持同步的组成部分: (1)局限于管程并仅能从管程内访问的若干条件变量(condition); (2)对条件变量
29、进行操作的两个函数过程。 WaitC(C):将调用此函数的进程挂起并阻塞在与条件变量C相应的队列中,同时使其它进程可以进入管程。 SignalC(C):恢复某个由于在条件变量C上执行WaitC操作而被挂起阻塞的进程执行。若没有被挂起的进程,则执行空操作。一般要求SignalC(C) 为过程的最后一语句。,2019/6/13,51,例1:用管程实现生产者和消费者问题。仍然使用有K个缓冲区的环形缓冲区,每个缓冲区可容纳一个数据记录,in是缓冲区的尾指针,out为缓冲区的头指针。另外,再用fulll表示缓冲区已满的条件变量,用empty表示缓冲区已空的条件变量,用count表示当前缓冲区未取走的数据
30、记录数。,Monitor boundedbuffer product bufferK ; static int in = 0, out = 0 ,count = 0; /*初始化*/Condition full, empty ;,2019/6/13,52,public put( product x) if (count = K ) WaitC(full); /*缓冲区已满,等待*/bufferin = x ;in = (in+1) % K;count +;SignalC( empty ); public get( product *x) if(count = 0 ) WaitC(empty);
31、 /*缓冲区已空,等待*/*x = bufferout ;out = (out+1) % K;count -;SignalC( full ); ,2019/6/13,53,process produceri product x ;生产一件物品x;boundedbuffer.put(x) ;/*调用管程过程,将物品放入缓冲区*/ process consumerj product y ;boundedbuffer.get(/*调用管程过程,从缓冲区中取物品*/ 消费一件物品y; ,2019/6/13,54,例2 用管程实现读者写者问题:,Procedure start_read begin ch
32、eck(IM); if wc0 then wait(R,IM); rc:=rc+1; signal(R,IM);release(IM); end;,Procedure end_read begin check(IM); rc:=rc-1; if rc=0 then signal(W,IM) release(IM); end;,TYPE reader-writer=MONITOR var rc,wc:integer; var R,W:semaphore; define start_read,end_read,start_write,end_write; use wait,signal,check
33、,release;Hansen定义的四条原语,2019/6/13,55,Procedure stare_write begin check(IM); wc:=wc+1; if(rc0) or (wc1) then wait(W,IM); release(IM); end;,Procedure end_write begin check(IM); wc:=wc-1; if(wc)0 then signal(W,IM) else signal(R,IM); release(IM); end;,2019/6/13,56,cobegin,Process reader begin call reader
34、_writer.start_read; read(F); . call reader_writer.end_read; end;,Process writer begin call reader_writer.start_write; write(F); call reader_writer.end_write; end;,coend,2019/6/13,57,例3 桌上有一只盘子,每次只能放入一只水果。爸爸专放苹果,妈妈专放橘子,一个儿子专等吃盘子中的橘子,一个女儿专等吃盘子中的苹果。分别用P,V操作和管程实现。,(1)用p,v操作实现:(Pascal形式表示),empty,full1,fu
35、ll2:semaphore; empty:=1;full1:=0;full2;=0; Cobegin repeat farther; repeat mother; repeat son; repeat daughter; Coend;,2019/6/13,58,Procedure father; begin P(empty); 放苹果入盘; V(full1); end; procedure mother; begin P(empty); 放橘子入盘; V(full2); end;,Procedure son; begin P(full2); 从盘中取橘子; V(empty);吃橘子;end;
36、procedure daughter begin P(full1); 从盘中取苹果; V(empty); 吃苹果;end;,2019/6/13,59,(2) 用管程实现:,TYPE FMSD=MONITER var plate:(app;e,orange); full,boolean; sp,ss,sd:semaphore; define put,get; use wait,signal,check,release; procedure put(var fruit:(app;e,orange); begin check(IM); if full then wait(sp,IM); full:=
37、true; plate:=fruit; if p;ate=orange then signal(ss,IM); else signal(sd,IM); end,2019/6/13,60,Procedure get(var fruit:(apple,orange),x:plate);begin check(IM); if full=false or plate not in fruit then begin if fruit=orange then wait (ss,IM); else wait(sd,IM); end; x:=plate; full:=false; signal(sp,IM); release(IM); end; begin full:=false; sp:=0; ss:=0; sd:=0; end;,2019/6/13,61,爸爸妈妈向盘中放水果时调用过程put,子女要取水果时调用过程get.即:,Cobegin process father begin 准备好苹果; call FMSD.put(apple); end;,