如何用结构型信号量实现互斥和同步
信号量方法的基本原则:两个或多个进程可以用信号的方法进行协作;进程可以在任何地方停下来以等待收到特定的信号;信号的实现是用一种称为信号量(Semaphore)的特殊变量。信号量S就是一个特殊变量,包含一个整数值。在S上可以执行两个原子操作:**wait(S)**用来接受信号,也称为P操作;**signal(S)**用来发送信号,也称为V操作。信号量分类:计数信号量(Counting Sema...
信号量方法的基本原则:两个或多个进程可以用信号的方法进行协作;进程可以在任何地方停下来以等待收到特定的信号;信号的实现是用一种称为信号量(Semaphore)的特殊变量。
信号量S就是一个特殊变量,包含一个整数值。
在S上可以执行两个原子操作:wait(S)用来接受信号,也称为P操作;signal(S)用来发送信号,也称为V操作。
信号量分类:计数信号量(Counting Semaphore)、二元信号量(Binary Semaphore)、结构信号量(Structure Semaphore),
结构型信号量
结构型信号量数据结构
typedef struct
{
int value;
struct process *L; // L指向一个进程队列
}
wait操作
void wait(semaphore *S)
{
s.value--;
if (s.value < 0)
{
add this process into S.L;
block();
}
}
signal操作
void signal(semaphore *S)
{
s.value++;
if (s.value <= 0)
{
remove a process P from S.L;
wakeup(P);
}
}
如何用信号量实现互斥?
用信号量实现互斥的方法:
(S.value初始值为1)
wait(S);
临界区
signal(S);
例如:有三个进程P、Q、R欲进入临界区,S.value初始值为1。P进入时,先执行wait(S),此时S.value=0,不满足if条件,则wait结束,P进入临界区。若此时Q想要进入临界区,也需执行wait,此时S.value=-1,满足<0条件,则将进程加入S,L,block阻塞进程,使其等待。同理若R想进入临界区,则有S.value=-2,R进程也阻塞。
此时若P从临界区出来,执行signal,此时S.value=-1,满足if条件,从等待进程中选择一个进入临界区,假设按照FCFS算法,使Q进入。同理Q出临界区后,S.value=0,R进入,R出临界区后,S.value=1,回归初始值。
如何用信号量实现同步?
用信号量实现同步的方法:
S.value初始值为0
在先执行的进程段后面加signal(S)
后执行的进程段前面加wait(S)
例子:假设有P1和P2两个进程,要求P1进程的A段必须在P2进程的B段之前执行。
(1) 若此时P1先执行,执行完A段后,执行signal(S),此时S.value=1,不满足signal中的if条件,不进行任何操作,结束signal。再执行P2的B段之前,执行wait(S),此时S.value=0,不满足wait中的if条件,不进行任何操作,结束wait,执行B。
(2) 若此时P2先执行,执行B段之前先执行wait(S),此时S.value=-1,满足wait中的if条件,B段进入S.L队列,阻塞。执行P1中的A段,结束后执行signal(S),此时S.value=0,满足signal中的if条件,将B移出等待队列,唤醒B进程。
信号量取值特点
一个信号量的值可以为负数,其绝对值表示有多少个进程等待这个信号量。
一个信号量的值可以为正数,表示有一个或多个被积累下来的唤醒操作。
使用信号量时需要避免的错误
死锁:两个或多个进程无限地等待一个事件,而这个事件只能由这些等待进程之一来产生。
饥饿:无限期阻塞,即进程在信号内无限等待的情况。
参考文献
北京工业大学网课《操作系统原理》金雪云
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)