zoukankan      html  css  js  c++  java
  • 进程管理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

    参考资料

    《华东理工大学  操作系统》
     
  • 相关阅读:
    向强大的SVG迈进
    手把手教你写个小程序定时器管理库
    蒲公英 · JELLY技术周刊 Vol.11 Lighthouse 测试报告生成
    ES6语法——let和const
    北京天地益星面经
    JS的数据类型你真的懂了吗
    北京MedPeer凉经
    flex布局语法+实例
    面试官问:你有多少种方式实现三栏布局?
    CSS粘性定位
  • 原文地址:https://www.cnblogs.com/wuyudong/p/os-process-management2.html
Copyright © 2011-2022 走看看