信号量
Posted 神级游走
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了信号量相关的知识,希望对你有一定的参考价值。
信号量用来解决同步和互斥问题,只能被两个原语wait(S)和signal(S)访问。信号量分为整形信号量和记录型信号量:
1.整型信号量:
整形信号量表示资源的数目。wait和signal操作(P和V)可描述为:
wait(S)
while(S<=0);
S=S-1;
signal(S)
S=S+1;
wait操作中,只要信号量S<=0,就会不断的测试,使进程处于“忙等”状态,未遵循“让权等待”准则。
2.记录型信号量:
记录型信号量不存在“忙等”现象,遵循“让权等待”准则。
记录型信号量得名于采用了记录型的数据结构。包括:
1.一个用于代表资源数目的整型变量value。
2.一个进程链表L,用于链接所有等待该资源的进程。
typedef struct
int value;
struct process *L;
semaphore;
相应的wait(S)和signal(S)的操作如下:
void wait(semaphore S) //相当于申请资源
S.value--;
if(S.value<0)
block(S.L);
wait操作,S.value--表示进程请求一个该类资源,当S.value<0时,表示该类资源已分配完毕,因此进程应block原语,进行自我阻塞,放弃处理机,并将进程插入该资源的等待队列S.L,可见该机制遵循了“让权等待”原则。
void signal(semaphore S) //相当于释放资源
S.value++;
if(S.value<=0)
wakeup(P);
signal操作,表示进程释放资源,使可分配的资源数加1,因此有S.value++。若加1后资源数仍小于等于0,则表示再等待队列中仍有进程被阻塞,因此还应调用wakeup原语,将等待队列中第一个等待进程唤醒。
3.信号量实现进程同步:
设S为实现进程P1,P2同步的公共信号量,初值为0。进程P2中的语句y要使用进程P1中语句x的结果,所以只有x执行完才能执行y。
semaphore S=0;
P1()
...
x;
V(S); //告诉P2进程,语句x已经完成
...
P2()
...
P(S); //检查语句x是否完成
y;
...
若P2先执行到P(S),S为0,执行P操作会把进行P2阻塞,并放入阻塞队列;当进程P1中的x执行完后,执行V操作,把P2从阻塞队列唤醒,放回到就绪队列,当P2得到处理机就得以继续执行。
4.信号量实现进程互斥:
设S为实现进程P1,P2互斥的信号量,由于每次只允许一个进程进入临界区,所以S的初始值为1(即可用资源数为1).只需把临界区置于P(S)和V(S)之间,即可实现两个进程对临界资源的互斥访问。
semaphore S=1;
P1()
...
P(S); //准备开始访问临界资源,加锁
进程P1的临界区;
V(S); //访问结束,解锁
...
P2()
...
P(S); //准备开始访问临界资源,加锁
进程P2的临界区;
V(S); //访问结束,解锁
...
当没有进程在临界区时,任意一个进程要进入临界区,就要执行P操作,把S的值减为0,然后进入临界区;当有进程存在于临界区时,S的值为0,再有进程要进入临界区,执行P操作时将会被阻塞,直到再临界区的进程退出,这样便实现了临界区的互斥。
互斥是不同进程对同一信号量进行P,V操作实现的,一个进程成功对信号量执行了P操作后进入临界区,并在退出临界区后,由该进程本身对该信号量执行V操作,表示当前没有进程进入临界区,可以让其他进程进入。
总结一下PV操作在同步互斥中的应用:
在同步问题中,若某个行为要用到某种资源,则在这个行为面前P这种资源一下;若某个行为会释放某种资源,则在这个行为后面V这种资源一下。在互斥问题中,P,V操作要紧夹使用互斥资源的那个行为,中间不能有其他冗余代码。
参考:
王道操作系统复习指导
以上是关于信号量的主要内容,如果未能解决你的问题,请参考以下文章
有n个并发进程,设s是用于互斥的信号量,其初值s=3,当s=-2时意味啥
有N个并发进程,设s是用于互斥信号量,其初值s=3,当s=-2时,意味着( ),执行一个 P(s)操作