信号量机制

1965年,由荷兰学者迪科斯彻Dijkstra提出(P、V分别代表荷兰语的Proberen (test)和Verhogen (increment))、是一种卓有成效的进程同步机制。

信号量-软件解决方案

  • 保证两个或多个代码段不被并发调用
  • 在进入关键代码段前,进程必须获取一个信号量,否则不能运行
  • 执行完该关键代码段,必须释放信号量
  • 信号量有值,为正说明它空闲,为负说明其忙碌

信号量的类型可分为

  • 整型信号量
  • 记录型信号量(最为常用)
  • AND型信号量
  • 信号量集

信号量机制介绍

1、整型信号量

用一个整数型的变量 "S"作为信号量,用来表示系统中某种资源的数量。

wait(S) :
while S<=0; /*do no-op*/ 
    S:=S-1;

signal(S):
    S:=S+1;
  • 提供两个不可分割的[原子操作]访问信号量
  • Wait(s)又称为P(S)
  • Signal(s)又称为V(S)
  • 缺点:进程忙等 

2、记录型信号量

  • 为了解决“忙等”问题,而提出的信号量。
  • 每个信号量S除一个整数值S.value外,还有一个进程等待队列S.list,存放阻塞在该信号量的各个进程PCB
  • 信号量只能通过初始化和两个标准的原语PV来访问--作为OS核心代码执行,不受进程调度的打断
  • 初始化指定一个非负整数值,表示空闲资源总数(又称为"资源信号量")-- 若为非负值表示当前的空闲资源数,若为负值其绝对值表示当前等待临界区的进程数
typedef struct {
    int value;
    stuct process_control_block *list;
}semaphore;

相应地,wait(S)和signal(S)操作可描述为:

wait(semaphores *S) {  //请求一个单位的资源
    S->value --;  //资源减少一个
    if (S->value<0) block(S->list)  //进程自我阻塞
}

signal(semaphores *S){  //释放一个单位资源
    S->value++;  //资源增加一个
    if (S->value<=0) wakeup(S->list);  //唤醒等待队列中的一个进程
}

3、AND型信号量

  • AND型信号量同步的基本思想:将进程在整个运行过程中需要的所有资源,一次性全部分配给进程,待进程使用完后再一起释放
  • 对若干个临界资源的分配,采用原子操作。
  • 在wait(S)操作中增加了一个 “AND” 条件,故称之为AND同步,或同时wait(S)操作,即Swait(Simultaneous wait)。

4、信号量集

  • 在记录型信号量中,wait或signal能对某类临界资源进行一个单位的申请和释放,当需要对N个单位进行操作时,需要N次wait/signal操作,效率低下
  • 扩充AND信号量:对进程所申请的所有资源以及每类资源不同的资源需求量,在一次P、V原语操作中完成申请或释放
    • 进程对信号量Si的测试值是该资源的分配下限值ti,即要求Si≥ti,否则不予分配。一旦允许分配,进程对该资源的需求值为di,即表示资源占用量,进行Si= Si-di操作
    • Swait(S1, t1, d1, ..., Sn, tn, dn)
    • Ssignal(S1, d1, ..., Sn, dn)

信号量的应用

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

        key:设置互斥信号量

        为使多个进程能互斥地访问某临界资源,只须为该资源设置一个互斥型信号量mutex,并设其初值为1,然后将各进程访问该资源的临界区置于wait(mutex) 和signal(mutex)操作之间即可。
        这样,每个欲访问该临界资源的进程,在进入临界区之前,都要先对mutex执行wait操作。若该资源此刻未被访问,则本次wait操作必然成功,进程便可进入自己的临界区,这时若再有其他进程也欲进入自己的临界区,则由于对mutex执行wait操作定会失败,因而该进程阻塞,从而保证了该临界资源能被互斥地访问。当访问临界资源的进程退出临界区后,又应对mutex执行signal操作,以便释放该临界资源。

利用信号量实现两个进程互斥的描述如下。

  1. 设mutex为互斥型信号量,其初值为1,取值范围为(-1,0,1)。当mutex=1时,表示两个进程皆未进入需要互斥访问的临界区;当mutex=0时,表示有一个进程进入临界区运行,另一个必须等待,挂入阻塞队列;当mutex=-1时,表示有一个进程正在临界区运行,而另一个进程因等待而阻塞在信号量队列中,需要被当前已在临界区运行的进程在退出时唤醒。
  2. 代码描述:
    semaphore mutex=1;  //初始化为1
    
    PA(){
        while (1){
        wait (mutex);
        临界区;
        signal (mutex);
        剩余区;
        }
    }
    
    PB(){
        while (1){
        wait (mutex);
        临界区;
        signal (mutex);
        剩余区;
        }
    }
    

在利用信号量机制实现进程互斥时应注意,wait(mutex) 和 signal(mutex)必须成对出现。缺少wait(mutex)将会导致系统混乱,无法保证对临界资源的互斥访问;缺少signal(mutex)将会导致临界资源永远不被释放,从而使因等待该资源而阻塞的进程不能被唤醒。

2、利用信号量实现前趋关系

信号量机制_第1张图片

main (){
Semaphore a,b,c,d,e,f,g;

a.value=0;b.value=0;c.value=0;
d.value=0;e.value=0;f.value=0;g.value=0;

cobegin
    { S1 ;signal(a);signal(b); }
    { wait(a);S2;signal(c);signal(d);}
    { wait(b);S3;signal(e); }
    { wait(c);S4;signal(f); }
    { wait(d);S5;signal(g); }
    { wait(e);wait(f);wait(g);S6; }
corend
}

3、利用信号量实现进程同步

        key:设置同步信号量

        假设进程P1和P2中有两段代码C1和C2,若要强制C1先于C2执行,则须在C2前添加wait(S),在C1后添加signal(S)。需要说明的是,信号量S的初值应该被设置为0。这样,只有P1在执行完C1后,才能执行signal(S)以把S的值设置为1。这时,P2执行wait(S)才能申请到信号量S,并执行C2。如果P1的C1没有提前执行,则信号量S的值为0,P2执行wait(S)时会因申请不到信号量S而阻塞。

  1. 设S为同步型信号量,其初值为0,取值范围为(-1,0,1)。当S=0时,表示C1还未执行,C2也未执行;当S=1时,表示C1已经执行,C2可以执行;当S=-1时,表示C2想执行,但由于C1尚未执行,C2不能执行,进程P2处于阻塞状态。
  2. 代码描述:
    semaphore S=0;  //初始化为0
    
    P1() {
        while (1) {
            C1
            signal(S);
            ...
        }
    }
    
    P2() {
        while (1) {
            wait(S);
            C2 ;
            ...
        }
    }
    

同步型信号量的使用通常比互斥型信号量的使用要复杂。一般情况下,同步型信号量的wait(S)和signal(S)操作位于两个不同的进程内。

Examples

1、请思考互斥与同步的关系,它们有哪些地方相同?哪些地方不同?

相同之处:

  1. 目的:互斥和同步都是为了协调多个进程对共享资源的访问,以避免竞争条件和数据不一致性。
  2. 都可以通过信号量、互斥锁等机制来实现。

不同之处:

  1. 定义:互斥是指在任意时刻只允许一个进程访问共享资源,而同步是指协调进程之间的交互和通信,确保它们按照一定顺序执行
  2. 目标:互斥的目标是防止多个进程同时访问共享资源,而同步的目标是确保进程按照特定顺序执行,或者在某个条件满足时进行通信和协调。
  3. 实现方式:互斥通常使用互斥锁或信号量来实现,而同步可以使用信号量、条件变量、屏障等机制来实现。

2、桌上有一空盘,允许存放一只水果。爸爸可向盘中放苹果,妈妈可向盘中放香蕉,儿子专等吃盘中的香蕉,女儿专等吃盘中的苹果,请按照要求回答:

        (1)本题中存在哪些互斥关系和同步关系?

        (2)试用P、V操作描述放水果和吃水果的过程。

答: (1)在本题中,盘中一次只能放一个水果;妈妈和爸爸对盘子的使用存在互斥关系,所以需要设互斥信号量mutex;爸爸和女儿,妈妈和儿子都是同步关系,需设置同步信号量apple, banana

        (2)设置信号量mutex, apple, banana,初值分别为100。分别表示可否向盘中放水果,可否取苹果,可否取香蕉。

代码段如下:   

Father(){   
    while (true){
        p(mutex);  //申请盘子使用权
        将苹果放入盘子;
        v(apple);  //苹果产品+1
    }
}

Mother(){  
    while (true){
        p(mutex);  //申请盘子使用权
        将香蕉放入盘子;
        v(banana);  //香蕉产品+1
    }
}

son(){  
    while (true){
        p(banana);  //申请香蕉资源,若非空
        从盘子取香蕉;
        v(mutex);   //盘子空了,释放盘子使用权
        吃香蕉;
    }
}

daugher(){  
    while (true){
        p(apple);  //申请苹果资源,若非空
        从盘子取苹果;
        v(mutex);  //盘子空了,释放盘子使用权
        吃苹果;
    }
}

3、公共汽车上有1名司机和1名售票员,司机和售票员活动如下,车辆运行规则是只有到站停车后售票员才能开门,只有关门后司机才能启动车辆。初始状态是车辆停在起始站。使用P、V原语描述车辆运行过程。

分析:本例中存在同步关系,即只有售票员关门后司机才能启动车辆;只有司机到站停车后售票员才能开门;

故设置:

        司机的同步信号量: S1表示是否允许司机启动车辆,初值为0

        售票员同步信号量: S2表示是否允许售票员开门,初值为1

则车辆运行过程描述如下:

driver:
    while (true){
        P(S1);//申请启动车辆,若标志为1,则可以启动
        启动车辆;
        正常运行;
        到站停车;
        V(S2);
    }

conductor:
    while (true){
        P(S2); //申请开门,若标志为1,则可以开门
        开门;
        售票;
        关门;
        V(S1);
    }

你可能感兴趣的:(Operating,System,操作系统,期末复习,学习)