进程管理2--进程的同步与信号量

本文地址:http://www.cnblogs.com/archimedes/p/os-process-management2.html,转载请注明源地址。

进程同步

进程同步:指对多个相关进程在执行次序上进行协调;

同步的任务:使系统中各进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性;

系统中各进程之间在逻辑上的相互制约的关系:

直接关系—同步

间接关系—互斥

用来实现同步的机制称为同步机制。如:
  • 软件和硬件的方法;
  • 信号量机制;
  • 管程机制
进程同步的基本概念
  • 两种形式的制约关系
  • 临界资源、临界区
  • 同步机制应遵循的规则
信号量机制
  • 整型信号量
  • 记录型信号量
  • AND型信号量集、一般信号量集
信号量的应用
  • 信号量实现进程互斥
  • 信号量描述进程间的前趋关系
管程机制

进程同步的基本概念

1、进程之间两种形式的制约关系

系统中各进程之间在逻辑上存在着两种制约关系:

直接相互制约关系/相互合作关系(进程同步):

      即为完成同一个任务的各进程之间,因需要协调它们的工作而相互等待、相互交换信息所产生的直接制约关系。   

间接相互制约关系/资源共享关系(进程互斥):

     是进程共享独占型资源而必须互斥执行的间接制约关系。

同步与互斥比较:

2、临界资源、临界区

一次只允许一个进程使用的共享资源称为临界资源,如打印机,绘图机,变量,数据等,各进程间采取互斥方式实现对这种临界资源的共享,从而实现并发进程的封闭性。

例:生产者-消费者问题

      一组生产者向一组消费者提供产品,它们共享一个缓冲池,生产者向其中投放产品,消费者从中取得产品。它是许多相互合作进程的抽象,如输入进程与计算进程;计算进程与打印进程等。

      设缓冲池的长度为n(n>0),一群生产者进程P1,P2,…,Pm,一群消费者进程C1,C2,…,Ck,如图所示。假定生产者和消费者是相互等效,只要缓冲池未满,生产者就可以把产品送入缓冲区,类似地,只要缓冲池未空,消费者便可以从缓冲区取走产品并消耗它。

      生产者和消费者进程是以异步方式运行的,但必须保持同步关系,即禁止生产者向满的缓冲池输送产品,也禁止消费者从空的缓冲池提取产品。

生产者消费者进程共享如下变量:
int n;  //n为缓冲池中缓冲区的个数;
buffer:array[0..n-1] of item;  //buffer为具有n个缓冲区的缓冲池;
in,out:0..n-1;  //in和out为指针,分别指向下一个可投放产品的缓冲区和下一个可获取产品的缓冲区
counter:0..n;
生产者消费者进程可分别描述为:
void producer()  //生产者
{
   while(1) {
     ……
     produce an item in nextp;  //生产一个产品
     ……
     if (counter <= n) {   //当生产的数目等于count的时候停止
         buffer[in] = nextp;
         in = (in + 1) mod n;  
         counter = counter + 1;
     } else {
        break;
     }
   }
}

void consumer()  //消费者
{
   while(1) {
       while (counter > 0) {
           nextc = buffer[out];
           out = (out + 1) mod n;
           counter = counter - 1;
           consume the item in nextc;  //消费一个产品
       }
       break;
    }
}
并发执行时会出现差错,问题出在两进程共享的变量counter上 

用机器语言实现变量的加1、减1的操作为:

//变量counter加1:  
register1 = counter;
register1 = register1 + 1;
counter = register1;

//变量counter减1:  
register2 = counter;
register2 = register2-1;
counter = register2;

若按另一顺序对变量进行修改,会得到什么结果?

register1 = counter;
register1 = register1 + 1;
register2 = counter;
register2 = register2 - 1;
counter = register1;
counter = register2;

为了保证临界资源的正确使用,可以把一个访问临界资源的循环进程描述如下:

进入区(Entry Section)

增加在临界区前面的一段代码,用于检查所要访问的临界资源此刻是否被访问。

退出区(Exit Section)

增加在临界区后面的一段代码,用于将临界资源的访问标志恢复为未被访问标志。

剩余区(Remainder Section)

进程中除了进入区、临界区及退出区之外的其余代码。

要进入临界区的若干进程必须满足:

(1)一次只允许一个进程进入临界区

(2)任何时候,处于临界区的进程不得多于一个

(3)进入临界区的进程要在有限的时间内退出

(4)如果不能进入自己的临界区,则应让出处理机资源

解决临界区(互斥)问题的几类方法:

(1)软件方法和硬件方法

(2) P-V操作

(3)管程机制

3、同步机制应遵循的规则

  • 空闲让进:当无进程处于临界区时,表明临界资源处于空闲状态,应允许一个请求进入临界区的进程立即进入自己的临界区,以有效地利用临界资源。

  • 忙则等待:当已有进程进入临界区时,表明临界资源正在被访问,因而其他试图进入临界区的进程必须等待,以保证对临界资源的互斥访问。

  • 有限等待:对要求访问临界资源的进程,应保证在有限时间内能进入自己的临界区,以免陷入“死等”状态。

  • 让权等待:当进程不能进入自己的临界区时,应立即释放处理机,以免进程陷入“忙等”。

信号量机制

信号量机制是荷兰科学家E.W.Dijkstra在1965年提出的一种同步机制,也称为P、V操作。由最初的整型信号量发展为记录型信号量,进而发展为信号量集机制。

1、整型信号量

整型信号量——非负整数,除了初始化(即赋初值:必须置一次且只能置一次初值,初值不能为负数)外,只能通过两个原子操作wait和signal(或者叫P、V操作)来访问(即信号量的值仅能由这两个原子操作来改变 )。
wait和signal操作描述:

   wait(S): while S <= 0  do no-op; 测试有无可用资源

             S = S - 1;   可用资源数减一个单位

   signal(S): S = S + 1;

主要问题:只要S <= 0, wait操作就不断地测试(忙等),因而,未做到“让权等待”。

2、记录型信号量

基本思想

       1、设置一个代表资源数目的整型变量value(资源信号量)

       2、设置一链表L用于链接所有等待访问同一资源的等待进程

记录型信号量的数据结构

     Type semaphore=record

                      value:integer;

                      L: list of process;

                    end

     Var  S: semaphore;

wait和signal操作描述:
//调用阻塞原语将该进程状态置为
//等待状态,将该进程的PCB插入
//相应的等待队列S.L末尾;
  wait(S):  
      S.value:=S.value-1;    
      if S.value<0 then
         block(S.L);

//调用唤醒原语唤醒相应等待队列
//S.L中等待的一个进程,改变其状
//态为就绪态,并将其插入就绪队列
  signal(S): 
      S.value:=S.value+1;  
      if S.value£0  then
         wakeup(S.L);

在记录型信号量机制中:

S.value的初值表示系统中某类资源的数目。

S.value的初值为1,S为互斥信号量;

S.value的初值大于1,S为资源信号量;

在记录型信号量机制中

每次wait(S)操作意味着进程请求一个单位的资源,资源数目减1。当S.value<0时表示资源已分配完毕,进程调用Block()原语进行自我阻塞,放弃处理机,并插入到信号量链表S.L中。此时,|S.value| 表示在该信号量链表中已阻塞进程的数目。

每次signal(S)表示执行进程释放一个单位资源,资源数目加1。若加1后仍有S.value<=0,则表示在该信号量链表中,还有等待该资源的进程,则调用Wakeup()原语,将链表中第一个进程唤醒。

AND型信号量(了解

一般信号量集(了解

信号量的应用

1、利用信号量实现进程互斥

    利用信号量可以方便地解决临界区问题(进程互斥)(见后面的图)。为临界资源设置一互斥信号量lock,初值为1,则实现进程A、B、C互斥的描述:

 
完整的运行顺序图如下:

2、利用信号量描述前趋关系

方法:

     若图中存在结点S1指向结点S2的有向边,表示进程P1中的程序段S1应该先执行,而进程P2中的程序段S2后执行。设置一个信号量s,初值为0,将V(s)放在S1后面,而在S2前面先执行P(s)。

进程P1的语句序列为:S1;V(s)

进程P2的语句序列为:P(s);S2

例:利用信号量来描述前趋图关系

具有8个结点的前趋图。前趋图中共有有向边10条,可设10个信号量,初值均为0;有8个结点,可设计成8个并发进程,具体描述如下:
struct semaphore a,b,c,d,e,f,g,h,i,j=0,0,0,0,0,0,0,0,0,0
cobegin 
    {S1;V(a);V(b);V(c);}
    {P(a);S2;V(d);}
    {P(b);S3;V(e);V(f);}
    {P(c);S4;V(g);}
    {P(d);P(e);S5;V(h);}
    {P(f);P(g);S6;V(i)}
    {P(h);P(i);S7;V(j);}
    {P(j);S8;}
coend

参考资料

《华东理工大学  操作系统》
 
posted @ 2014-09-12 19:24  wuyudong  阅读(1973)  评论(0编辑  收藏  举报
Top_arrow