信号量(Semaphores)机制——进程同步工具
由DIjkstra提出,目前已广泛应用于单处理机和多处理机系统以及计算机网络中。
一、整形信号量
1.S:一个用于表示资源数目的整型量;
2.与一般整型量不同,除初始化外,仅能通过两个标准的原子操作:wait(S)和signal(S);长期以来一直被称为P、V操作;
3.wait操作伪码描述:
wait(S){
while(S<=0); //do no-op
S--;
}
4.signal操作伪码描述:
signal(S){
S++;
}
5.上述两个操作是原子操作,执行时不可中断。即:当一个进程在修改某信号量时其他进程不可同时对该信号量进行修改;在wait操作中,对S值的测试和做S=S-1操作均不可中断;
6.wait操作中,只要S<=0,就会不断进行测试;未遵循“让权等待”准则,进程一直处于“忙等”状态。
二、记录型信号量
1.伪码描述:
typedef struct{
int value; /*代表资源数目*/
struct process_control_block *list; /*进程链表指针list,用于链接上述的所有等待进程*/
}semaphore;
/*记录型信号量机制中,S->value的初值表示系统中某类资源的数目,又称资源信号量*/
wait(semaphore *S){
S->value--; /*每次wait操作,意味着进程请求一个单位的该类资源,使系统中可供分配的该类资源数减少一个*/
if(S->value<0) block(S->list); /*表示该类资源已分配完毕,进程调用block原语进行自我阻塞,放弃处理机,并插入到信号量链表中*/
/*此时S->value的绝对值表示在该信号量链表中已阻塞进程的数目*/
}
/*对信号量的每次signal操作表示执行进程释放一个单位资源,使系统中可供分配的该类资源数增加一个*/
/*如果S->value的初值为1,表示只允许一个进程访问临界资源,此时的信号量转化为互斥信号量,用于进程互斥*/
signal(semaphore *S){
S->value++; /*表示资源数加1*/
if(S->value<=0) wakeup(S->list); /*在该信号量链表中仍有等待该资源的进程被阻塞,调用wakeup原语,将S->list链表中的第一个等待进程唤醒*/
}
2.记录型信号量由于采用记录型数据结构得名;
3.该机制遵循了“让权等待”准则;但会出现多个进程等待访问同一临界资源的情况,即死锁状态,进程同时要求共享地资源愈多,发生进程死锁地可能性愈大。
三、AND型信号量
1.AND同步机制基本思想:将进程在整个运行过程中需要的所有资源,一次性全部地分配给进程,待进程使用后再一起释放;即:对若干个临界资源地分配采取原子操作方式,要么把它所请求地资源全部分配到进程,要么一个也不分配;类似于分治法思想;
2.可在一定程度上避免死锁现象地发生;
3.伪码描述:
Swait(S1,S2,…,Sn){
while(TRUE){
if(Si>=1&&…&&Sn>=1){
for(i=1;i<=n;i++) Si--;
break;
}else{
place the process in the waiting queue associated with the first Si found with Si<1,and
set the program count of this process to the beginning of Swait operation
}
}
}
Ssignal(S1,S2,…,Sn){
while(TRUE){
for(i=1;i<=n;i++){
Si++;
Remove all the process waiting in the queue associated with Si into the ready queue
}
}
}
4.当一次需要N个单位时,AND型信号量效率较低,甚至会增加死锁概率;
5.在有些情况下,为确保系统的安全性,当所申请某类资源数量低于某一下限值时,必须进行管制不予分配;当进程申请某类临界资源时,在每次分配之前都必须测试资源的数量,判断是否大于可分配的下限值,决定是否予以分配。
四、信号量集
1.信号量集思想:对AND信号量机制进行补充,对进程所申请地所有资源以及每类资源不同地资源需求量,在一次P、V原语操作中完成申请或释放;
2.进程对信号量Si的测试值不再是1,而是该资源分配下限ti,即要求Si>=ti,否则不予分配;一旦允许分配,进程对该资源的需求量为di,即表示资源占有量,进行Si=Si-di操作;
3.Swait和Ssignal格式:
Swait(S1,t1,d1,…,Sn,tn,dn);
Ssignal(S1,d1,…,Sn,dn);
4.信号量集的几种特殊情况:
1>Swait(S,d,d)——信号量集中只有一信号量S,但允许每次申请d个资源,现有资源数<d时,不予分配;
2>Swait(S,1,1)——信号量集蜕化为一般的记录型信号量(S>1)或互斥信号量(S=1);
3>Swait(S,1,0)——S>=1时允许多个进程进入某特定区;S变为0后,将阻止任何进程进入特定区;即:相当于一个可控开关。