1. 程式人生 > 其它 >訊號量詳解

訊號量詳解

技術標籤:作業系統佇列多執行緒作業系統queue

2.14 訊號量(重點)

程序通過傳遞訊號進行協作

  • 程序因為某個條件阻塞,不能繼續推進
  • 程序因為某個條件被喚醒,可以繼續推進
可以實現訊號燈作用的整數變數:訊號量

訊號量的三種操作

  • 初始化:初始化為非負數,代表某種初始狀態
  • 自增semSignal(操作代號:V):該操作使訊號量+1,若此時訊號量仍<=0,喚醒被P操作阻塞的程序
  • 自減semWait(操作代號:P):該操作使訊號量-1,若此時訊號量<0,則阻塞執行P該操作的程序

2.14.1 訊號量分類

  • 二元訊號量:訊號量值為0/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操作的持續時間內遮蔽中斷,這些操作的持續時間相對較短,意味著這種方法是合理的。