1、4.1 基本概念,在多道程序运行环境中,一个进程的运行不是孤立的,往往取决于其他进程的活动。这不仅使诸进程的推进速度不可预知,而且也给操作系统的管理带来困难,4.1 基本概念,存款记录,进程A,100元,进程B,100,100,600,500,100,600,100,50,取款50,存款500,write,read,read,write,中断,继续,4.1 基本概念,终端A,终端B,x,y,y,y,键入字符x,回显字符y,键入字符y,回显字符y,write,read,read,write,Chin单元,中断,继续,4.1.1临界资源和临界区,临界资源(critical resources):
2、系统中多个进程可共享的、但某时刻只能为一个进程服务的资源。,4.1.1临界资源和临界区,互斥访问要求,操作系统在管理可控制资源分配与使用方面,应当保证进程对临界资源的访问满足以下三点:,不至于产生“死锁”,不能有“饥饿”进程,4.1.1临界资源和临界区,临界区 (critical section): 是进程中访问临界资源的程序和代码。 每个使用该资源的进程都要包含一个临界区。,声明进入临界区,临界区,声明退出临界区,4.1.2互斥准则,操作系统应确 保四项基本准则,空闲让进,忙则等待,有限等待,让权等待,4.2 软件方法,软件方法是针对单处理机或者共享内存的多处理机系统设计的方法,以实现存储器
3、访问中的互斥要求。这种方法并不依赖于硬件或操作系统的任何支持,纯粹用软件实现。对多个进程同时访问同一临界资源的要求,虽然没有预先规定访问顺序,但系统的仲裁机制能够按软件中的规定将其串行化。,Dekker方法,Peterson算法,Peterson算法,4.2.1 Dekker方法,早在1965年之前,荷兰数学家Dekker曾提出一种用于两个进程的互斥方法 ,该方法经历了四个阶段错误尝试而得到:,Dekker方法,第一次,第二次,第三次,第四次,4.2.1 Dekker方法,Dekker方法,第一次尝试,该算法中设计了一个变量turn 保存允许进入临界区的进程编号(初值为1,表示进程1可以首先进
4、入)。当一个进程要求进入临界区时,先检验trun 的值。若 turn 保存的不是自己的进程编号就进行循环等待;否则进入临界区。访问完成后退出临界区,再将 trun 设置为对方的进程编号。两个进程可描述如下:,Process(1)Begin While (turn 1)do skip; Critical section; turn =2; End,Process(2)Begin While (turn 2)do skip; Critical section; turn =1; End,缺点:该算法是一种强制交替机制,过于死板。 如果当trun=1时,而P1又不去访问临界资源,则P2将一直得不到临
5、界资源的访问权。,4.2.1 Dekker方法,Dekker方法,第二次尝试,该算法中定义了一个标志数组 Flag。当 Flagi=true,表示进程正在临界区。初始时 Flag 的各分布量值为False,表示无进程进入。当一个进程要求进入临界区时,先检查是否已有进程进入。若有就循环等待;否则,设置自己的标志为真,立即进入。访问完成后再将自己的标志设为假,Process p(1) Begin While (Flag2)do skip; Flag1=true; Critical section; Flag1=false; End,Process p(1) Begin While (Flag1)d
6、o skip; Flag2=true; Critical section; Flag2=false; End,缺点:两个进程可能同时进入临界区,该算法可能破坏“忙则等待”,4.2.1 Dekker方法,Dekker方法,第三次尝试,前一次尝试中,声明进入临界区的语句有两个:第一个进行测试与等待,第二设置访问标志。如果将这两个语句顺序互换,先设置好访问标志后再测试与等待,将不会出现多进程同时进入临界区的现象。,Process p(1) Begin Flag1=true; While (Flag2)do skip; Critical section; Flag1=false; End,Proces
7、s p(2) Begin Flag2=true; While (Flag1)do skip; Critical section;Flag2=false; End,缺点:两个进程可能都以为对方进入了临界区,从而造成死锁,破坏了“空闲让进”的准则,4.2.1 Dekker方法,Dekker方法,第四次尝试,这是一个“礼让为先”的算法,每个进程设置好自己的Flag标志,表明希望进入临界区。如果对方早已有访问的请求,则清除自己的 Flag,以表示谦让。此刻若丢失控制权,对方可进入;否则重置自己的 Flag。,Process p(1) Begin Flag1=true; While (Flag2)do
8、Flag1=false;Flag1=ture; Critical section; Flag1=false; End,Process p(2) Begin Flag2=true; While (Flag1)do Flag2=false;Flag2=ture; Critical section; Flag2=false; End,缺点:两个进程可能都以为对方进入了临界区,从而造成死锁,破坏了“空闲让进”的准则,4.2.1 Dekker方法,Dekker方法,第四次尝试,Process p(1) Begin Flag1=true; While (Flag2)do Flag1=false;Flag1
9、=ture; Critical section; Flag1=false; End,Process p(2) Begin Flag2=true; While (Flag1)do Flag2=false;Flag2=ture; Critical section; Flag2=false; End,缺点:算法的问题是进程因礼让太多可能会造成所谓的“活锁”。,Flag1 = ture;检查Flag2;将 Flag1 =false;.,Flag2 = ture;检查Flag1;将 Flag2 =false;,4.2.1 Dekker方法,Dekker方法,正确的方法,为了避免过度互斥礼让的问题,Dek
10、ker利用第一种尝试中的轮盘变量turn表示当前哪个进程有权进入临界区,强制性地规定进程活动顺序。算法如下:,Process P(1) Begin Flag1=true; While(Flag2) do if (turn=2) Flag1=false; While (turn=2) do skip Flag1=turn; Critical section; turn=2; Flag1=false; End,Process P(2) Begin Flag2=true; While(Flag1) do if (turn=1) Flag1=false; While (turn=1) do skip
11、Flag2=turn; Critical section; turn=1; Flag2=false; End,4.2.1 Dekker方法,Dekker方法,正确的方法,换一种表达如下,Process P(1) Begin Flag1=true; if(Flag2) if (turn=2) Flag1=false; While (turn=2) do skip Flag1=turn; else Critical section; endif turn=2; Flag1=false; End,Process P(2) Begin Flag2=true; if(Flag1) if (turn=1)
12、 Flag1=false; While (turn=1) do skip Flag2=turn; else Critical section; endif turn=1; Flag2=false; End,4.2.2 Peterson方法,Process P(1) Begin Flag1=true; turn=2; While (Flag2turn=2) do skip; Critical section; Flag1=false; End.,Process P(2) Begin Flag2=true; turn=1; While (Flag1turn=1) do skip; Critical
13、 section; Flag2=false; End.,该算法符合空闲让进和忙则等待原则。不过,该算法中的等待还不是让权等待,属于“忙等”方式。,4.3 硬件方法,纯软件方式,实现资源互斥访问,繁琐,硬件指令,存储单元,本身只能互斥,一条指令,存储单元,实现两条操作,存储单元,交 换,最常见的指令有两种:交换指令和测试与设置指令。,4.3.1交换指令,XCHG,op1,实现两条操作,op2,交 换,机器指令XCHG op1,op2,op2,op1,交 换,4.3.1交换指令,Var Boolean: lock :=false; /lock为全局变量 BeginParbegin process
14、(1) , , process (N) parend ; End;,Procecedure Process(i) Begin Key :=true ; /Key为局部变量 Repeat / 循环等待 XCHG(lock,key); Until key =false ; / 直到加锁成功 Critical section ; Lock := false ; End .,4.3.1测试与设置指令,该指令将状态测试和状态设置集于一条指令中,形成一个原子操作。也就是说,两个操作的执行不受中断信号的干扰。下面将指令格式定义为TS( ),其功能是读出一个指定变量的值,同时将一个新值置入。,Function
15、 TS(Lock) Begin TS :=Lock ; Lock :=true ; End ;,Key=TS(Lock),Key=Lock的当前状态,Lock调用后的值=true,第一个作用,第二个作用,4.3.1测试与设置指令,Var Boolean: mutex :=false; /全局变量 BeginParbegin process (1) , , process (N) parend ; End;Procedure Process(i) Begin While(TS(mutex) do skip; /循环等待 Critical section ; /进入 Mutex := false
16、; /释放 End .,TS(mutex),返回mutex的当前状态,将mutex 值设为true,第一个作用,第二个作用,4.4 信号量机制,Dijkstra,信号量机制,Semaphore,P操作,V操作,4.4 信号量机制,临界资源1,信号量S1,P(Si)操作,V(Si)操作,临界资源2,信号量S2,临界资源i,信号量Si,申请临界资源i的操作,释放临界资源i的操作,4.4.1整型信号量,临界资源,信号量S=1,P(S)操作,V(S)操作,while s=0 do skip;s=s-1;,S=S+1;,PV操作以原语方式执行,4.4.1整型信号量,临界资源,信号量mutex =1,P(
17、mutex),V(mutex),Process P(i) Begin ,Critical section;, End.,4.4.1整型信号量,一个用整型信号量机制实现进程同步的例子:假设有一个储存变量x ,用来传递计算机进程calculator和打印进程printer的数据。前者将计算的数据存入item,后者读出item的内容送往打印机,如此周而复始的不断下去。Item作为两个进程的共享资源,必须一次只能有一个进程访问,因此应将item视为临界资源。,calculator,printer,x,Doc,4.4.1整型信号量,Versino 1: 用了一个整型信号量mutex,初始值为1,表示变量
18、item正处于空闲状态。,Process caculater() BeginWhile(true) doBeginnextp1=Compute();P(mutex);item := nextp1;V(mutex); End End.,Process Printer() Begin While(true) doBeginP(mutex);nextp2 :=item ;V(mutex);Print(nextp2);End End.,Version1 可以成功地实现临界资源的互斥使用,但无法实现进程同步.,4.4.1整型信号量,Versino 2:设计两个信号s1和s2。前者用来制约计算进程重复往i
19、tem中放数,后者阻止打印进程重复从item中取数。s1的初始值设为1,s2的初始值设为0,允许计算进程首先访问item将数据放入。,Process calculate ()BeginWhile ( true ) doBeginnextp1=Compute();P(s1);Item:=nextp1;V(s2);EndEnd,Process print()BeginWhile ( true ) doBeginP(s2);Nextp1:= item;V(s1);Print (nextp2);EndEnd,Version2 可以成功地实现临界资源的互斥使用,同时实现进程同步.,4.4.2记录型信号量
20、,记录型信号量机制实现了“让权等待”功能。 一个记录型信号量包含两个分量:信号量的值和相应等待队列的指针. Type semaphore = recordValue : integer; / -N,+M*L : integer; /相应等待队列的指针 End.,s.value=s.value-1; if s.value0 do block(s.L);,s.value=s.value+1; if s.value=0 then wakeup(s.L);,P(s)操作,V(s)操作,4.4.2记录型信号量,例:假定在一个航空订票系统中,5个终端都可以通过与中心计算机连接,运行自己的进程。系统将某个航
21、班的座舱视为一个临界资源,并设有一个信号灯,那么,当终端进程需要访问某个航班(比如,3012巴黎航班)时,应当先用P原语访问该航班的信号量(比如为S),如果为绿灯就访问。,s.value=s.value-1; if s.value0 do block(s.L);,s.value=s.value+1; if s.value=0 then wakeup(s.L);,P(s)操作,V(s)操作,“访问3012巴黎航班的订票数据”,4.4.2记录型信号量,我们假设五个进程几乎同时访问S,其结果是第一个成功,其后四个相继被阻塞。,p,q,r,s,3012 航班数据,S的相关队列上有4个进程在阻塞,且S的
22、值减至-4,4.4.2记录型信号量,我们假设五个进程几乎同时访问S,其结果是第一个成功,其后四个相继被阻塞。,p,q,r,s,3012 航班数据,假设访问该航班的进程1访问完毕,通过执行自己的V(S),给S加1,使S的值变为-4+1=-3。由于S的值小于0,该进程需要从S的相关队列上摘下一个被阻塞的进程(将它转入就绪队列,使它可以访问3012航班,每当一个进程访问过该航班后,都唤醒一个进程。当4个阻塞进程访问完毕时,S的值递增至1 。 强烈提醒:被唤醒的进程访问S时不需要重新调用P(S),1、生产者-消费者问题,系统里有若干个合作的进程,其中: n(n0)个生产者进程、m(m0)个消费者进程、
23、以及由P(P0)个缓冲区组成的缓冲区环。,P1,P2,P3,Pn,S1,S2,S3,Sm,1、生产者-消费者问题,Var Semaphore: mutex:=1,Sin:=N,Sount :=0 Var Integer:in:=0,out:=0; Parbegin Producer( );Consumer( ) Parend.,Producer( ) BeginWhile (true) doBeginNextP1=Produce();/计算一个数据P(Sin);P(mutex);Bufferin := NextP1;/临界区in := (in+1)MOD N; V(mutex);V(Sout)
24、;End End.,Consumer() BeginWhite (true)BeginP(Sout)P(mutex)NextP2 := Bufferout; /临界区Out := (out + 1) MOD N;V(mutex);V(Sin);Consume(NextP2); /消费一个数据End End.,1、读者-写者问题,有一个数据块被多个用户共享,其中部分用户是读者,其他为写者。规定:读者对数据块是只读的,而且允许多个读者同时读取;写者对数据块是只写的,当一个写者正在向数据写入时,不允许其他用户操作。,data,2、读者-写者问题,Var Semaphore: mutex, Rmute
25、x :=1, 1; Var Integer: counter :=0 ; Parbegin Writer(i); Reader(j); Parend.,Procedure Writer(i) BeginWhile (true)Beginx=Calculate(); /计算一个数据P(mutex);data=Write(x); /临界区V(mutex);End; End. Process Reader(j),Process Reader(j) BeginWhile (true)BeginP(Rmutex);If counter = 0 then P(mutex);counter = counte
26、r + 1;V(Rmutex);Read(data); /共享读P(Rmutex);If counter = 1 then V(mutex);counter=counter 1;V(Rmutex);End; End.,3、哲学家用餐问题,3、哲学家用餐问题,设计一个信号量数组mutex0.4分别对应这5个筷子。 第i位哲学家的行为过程可描述为下面的形式。 Process Philosopher ( i ) Begin While (true) BeginThinking(); P(mutexi); /请求左筷子 P(mutexi+1mod 5); /请求右筷子 Eating(); /用餐过程
27、V(mutexi); /释放左筷子 V(mutexi+1 mod 5); /释放右筷子 End; End.,3、哲学家用餐问题,在这个算法中存在一个问题:假如当一个哲学家想用餐时,拿起左边的筷子后,其右邻得到控制权也拿起左筷子一时间5个哲学家都拿起左筷子,并且都在等待右筷子,于是5个人陷入死锁。,解决此类问题的方法有: 1、当多个哲学家同时饥饿时,系统要有限制 ,使至多不超过4个哲学家同时要求进餐,以确保至少有一人可以进餐。这样,当进餐者用餐完毕后释放两个筷子,就可以使更多的人进餐。 2、系统将椅子统一编号,让奇数号椅子上的哲学家饥饿时先拿起左筷子,偶数号椅子上的先拿右筷子。这样,1、2号哲学
28、家先竞争1号筷子,3、4号哲学家先竞争3号筷子,5号哲学家获得5号筷子。也就是说,获得奇数号筷子的哲学家只有3个人,他们再去竞争偶数号筷子。最终有人可获得进餐机会。 3、设计一种机制,让哲学家饥饿时,只用一个P操作就可以申请到两个筷子。若两个人不能同时申请到手,就将可能到手的筷子释放,让他人先进餐。这就是下一小节将要介绍的信号量集机制。,4. 4. 3 信号量集机制,信号量集机制是一种可同时获得多个资源的一种同步机制。,AND型信号量机制,一般型信号量集机制,4. 4. 3 信号量集机,这种机制中,让P原语具有同时给多个信号量减1的功能。不过,它要先判断各个信号量是否都是“绿灯”。若是,则将各
29、个信号量的值减1,立即进入临界区,若其中至少有一个信号量是“红灯“,进程就要让权等待,并将P原语的第1条指令作为断点地址,保存到该进程的PCB(上下文保护区)中,等回复运行时重执行P原语。P原语可描述如下:,1、AND型信号量机制,Procedure P(S1,Sn)BeginIf(S1=1 andand Sn=1)thenFor i= 1 to n DO Si := Si-1;ElsePCB(program counter) := addr(wait); /P操作的首址放于进程的上下文中Block(WLi); /进程阻塞End;End.,4. 4. 3 信号量集机,V原语将所有指定的信号量都
30、加1,表示释放所占的全部资源。注意,本次资源释放后有可能同时满足多个被阻塞的进程。因此,接下来需将各资源的所有等待着都唤醒,让它们重新执行自己的P操作去请求资源。,1、AND型信号量机制,Procedure V( S1,Sn)BeginFor I = 1 to n DOBeginSi := Si+1;For all Pi in WLi DO Wakeup (Pi);End;End.,4. 4. 3 信号量集机,1、AND型信号量机制,利用AND型信号量机制解决哲学家用餐问题:,Semaphore:mutex0:4=(1,1,1,1,1);ParBeginPhilosopher(1)Philos
31、opher(2)Philosopher(3)Philosopher(4)Philosopher(5)ParEnd;Process Philosopher(i)BeginWhile(true)BeginThinking();P(mutexi,mutexi+1mod 5);Eating();V(mutexi,mutexi+1mod 5);End End.,4. 4. 3 信号量集机制,定义:第i种临界资源的数量=Si 进程一次性地对第i种资源的请求量=di第i种资源的阈值=ti (当Siti时,便认为i种资源不可用),2、一般型信号量集机制,P(S1,t1,d1;S2,t2,d2,; Sn, tn
32、,dn,) Beginif (S1t1 and S2t2 and and Sntn)then for i:=1 to n doSi := Si-di ;endforelse PCB(program counter)= addr(wait);/将P的首址放入受阻进程的PCB上下文中Block(WLi).End End,V(S1,d1,S2,d2,Sn,dn,)for i:=1 to n doBeginSi:=Sidi;For all Pi in WLi DO Wakeup(Pi); End End,4. 4. 3 信号量集机制,3种信号量机制比较: 整形信号量机制比较简单,使用面较窄。记录形信号
33、量机制较为灵活,可用于多种同步场合。信号量集机制能够简化应用程序的设计,但系统的开销较大。,4.5 管 程(Monitor),为实现进程间的同步,在每个并发进程中都要设置大量的同步操作原语,这不仅给编程带来麻烦,且会因P操作使用不当而导致数据的不定性或死锁;同时也使操作系统结构不够清晰。1973年 Hansan和 Hoars提出了管程同步机制。,4.5 管 程 (Monitor),管程,一套初始化代码,管程的特征为: 1管理内的数据结构只能被管理内的过程访问,任何外部访问都是不允许的; 2.进程可通过调用管程的一个进程进入管程; 3.任何时间只允许一个进程进入管程,其他要求进入管程的进程统统被
34、阻塞到等待管程的队列上。,多个处理过程,局部数据结构,4.5 管 程 (Monitor),管程,初始化代码,过程1,数 据 结 构,过程2,过程n,条件 变量,条件 变量,受同步约束的队列,入口,进程队列,4.5 管 程 (Monitor),Type管程名 = Monitor Begin数据结构定义;局部变量定义;条件变量定义;Porcedure过程名(形式参数)Begin /过程体End;Begin /初始化End; End.,4.5 管 程 (Monitor),用管程解决生产-消费问题的例子:我们涉及的管程叫PC,利用传递产品的缓冲区环定义为一个数组buffer,并置于管程中。管程中的过程
35、有PUT()和GET(),分别实现产品的存入和取出。另外设计两个条件变量full和empty实现进程同步。Full:生产者的条件变量。当一个试图存放产品的生产者发现缓冲区环已经满时,将执行P(full)阻塞到full的关联队列上。Empty:消费者的条件变量。当一个试图取出产品的消费者发现缓冲区环已经空时,将执行P(empty)阻塞到empty的关联队列上。,Type PC = Monitor /定义管程PCBeginVar Char: bufferNVar Integer: counter,in,out;Var Condition: full, empty; /定义条件变量Porcedure
36、 PUT(item: char)BeginIf counter = N then P(full);Bufferin := item;In := (in+1) mod N;Counter := counter+1;V(empty) ;End;Porcedure GET(item: char)BeginIf counter = 0 then P(empty);item := Bufferout;out := (out +1) mod N;Counter := counter -1;V(full);End;Begin counter,in,out = 0,0,0; end; / 初始化 End.,4.5 管 程 (Monitor),Procedure Producer()BeginVar char: x;while (true)BeginProducer_an_item_in_x();PC.PUT(X); /调用PC的PUT过程End;End;,Procedure Consumer()BeginVar char: x;While (ture)BeginPC.GET(X); /调用PC的GET过程Consume_the_item_in_x();EndEnd.,4.6 进程通信,4.7 进程死锁讨论,