訊號量詳解
阿新 • • 發佈:2020-12-27
2.14 訊號量(重點)
程序通過傳遞訊號進行協作
- 程序因為某個條件阻塞,不能繼續推進
- 程序因為某個條件被喚醒,可以繼續推進
可以實現訊號燈作用的整數變數:訊號量
訊號量的三種操作
- 初始化:初始化為非負數,代表某種初始狀態
- 自增semSignal(操作代號:V):該操作使訊號量+1,若此時訊號量仍<=0,喚醒被P操作阻塞的程序
- 自減semWait(操作代號:P):該操作使訊號量-1,若此時訊號量<0,則阻塞執行P該操作的程序
2.14.1 訊號量分類
struct binary_semaphore{
enum { zero, one } value;
queueType queue;//內建佇列
};
void semwaitB(binary_semaphore s){//P操作
if(s.value == one)
s .value = zero;
else { //此時阻塞
place this process in s.queue;//當前程序加入阻塞佇列
block this process;//不是忙等,不佔cpu時間,等待喚醒
}
}
void semsignalB(semaphore s){//V操作
if( s.queue is empty())
s .value= one;
else {
remove a process P from s.queue;//從阻塞佇列取出程序
place process P on ready list;//喚醒阻塞程序
}
}
- 計數訊號量:即一般訊號量,訊號量取值範圍更大
struct semaphore {
int count;
queueType queue;
};
void semwait ( semaphore s ){//P操作
s.count--;
if ( s.count <0 ){
place this process in s.queue;
block this process;
}
}
void semsignal ( semaphore s){//V操作
s.count++;
if ( s.count <= 0 ){
remove a process P from s.queue;
place process P on ready list;
}
}
2.14.2 訊號量內部的佇列
- 強訊號量:程序按照FIFO移出
- 弱訊號量:不規定程序移出的順序
2.14.3 使用訊號量解決互斥問題
程序不能進行P操作時需要等待另一個程序的V操作,實現互斥
/* program mutualexclusion */
const int n = / *number of processes */;
semaphore s = 1 ;//初始化
void P(int i){
while (true){
semwait(s);//P操作:semaphore=1,可以--
/*訪問臨界區*/;
semsignal(s);//V操作:semaphore++
/*remainder*/;
}
}
void main (){
parbegin (P( 1),P( 2), . . ., P(n) ) ;
}
2.14.4 訊號量的實現
- semWait、semSignal作為原語實現
- 任意時刻僅有一個程序使用PV操作修訊號量
- 可以使用硬體實現
- 可以使用前面的機器指令實現
semWait (s){P操作
while (compare_and_swap(s.flag,0,1) == 1)//指令作用:s.flag=0?s.flag=1:;迴圈作用:s.flag=1跳出迴圈
/ *do nothing */;
s.count--;
if (s.count < 0) {
place this process in s.queue;
block this process (must also set s.flag to 0);
}
s.flag = 0;
}
semSignal(s){//V操作
while (compare and swap(s.flag, 0,1) == 1)//指令作用:s.flag=0?s.flag=1:;迴圈作用:s.flag=1跳出迴圈
/* do nothing */;
s.count++;
if (s.count <= 0){
remove a process P from s.queue;
place process P on ready list;
}
s.flag = 0;
}
- s.count ≥ 0, s.count 表示執行semWait(s)操作而不被阻塞的程序數(可看作可用資源數)。這種情形訊號量可支援同步與互斥。
- s.count < 0, s.count 表示阻塞在s.queue佇列上的程序數。
現在訊號量包含一個新的整數元素,s.flag,誠然,這可能導致一種新的忙等。然而,semWait和semSignal操作相對較短,所以涉及的忙等待量應該不大。對於單處理器系統,可以在semWait或semSignal操作的持續時間內遮蔽中斷,這些操作的持續時間相對較短,意味著這種方法是合理的。