信號量

一個信號是一個變量或抽象數據類型是用於控制訪問,由多個進程,以便在一個共同的資源併發系統如一個多道程序操作系統。

想在現實世界中的系統中使用的信號的一個有用的方式是提供一個特定資源的多少個單位,再加上操作的記錄,安全(即防止競態條件)調整了紀錄所需單位或變得自由,並且,如果需要的話,等到資源的單元變爲可用。信號量是在防止競爭條件的有用工具; 然而,它們的使用是絕不是保證一個節目是從上述問題的分類。信號燈允許任意的資源數量被稱爲計數信號,而這被限制在值0和1(或鎖定/解鎖,不可用/可用)信號燈稱爲二進制信號。

信號量的概念是由發明荷蘭 計算機科學家 Edsger Dijkstra算法在1962年或1963年,已經發現在各種廣泛使用的操作系統。它也被用作I / O控制器的控制機構,例如在Electrologica X8計算機。


當用於控制訪問池資源,信號量只跟蹤有多少資源是免費的; 它並不跟蹤其中的資源都是免費的。可能需要一些其他機制(可能涉及更多的信號量)來選擇特定的免費資源。
範例是特別強大,因爲信號計數可以用作許多不同的操作的有用的觸發。上述館長可關燈在自習時,有沒有剩餘的學生,也可以放置一個牌子,上面寫着房間都非常忙的時候大部分的客房都被佔用。
該協議的成功需要應用正確遵循它。公平性和安全性有可能受到影響(這實際上意味着一個程序可能會表現得慢,不穩定的行爲,掛起或崩潰),如果連一個單一的過程中的行爲不正確。這包括:
請求資源和忘記釋放;
釋放這是從來沒有請求的資源;
拿着很長一段時間,而不需要它的資源;
使用資源,而不首先請求它(或釋放它之後)。

即使所有的過程遵循這些規則,多資源死鎖時,有不同的信號和管理不同的資源,仍然可能發生,當流程需要同時使用多個資源,由所示哲學家就餐問題。

計數信號量都配有兩種操作,在歷史上記爲P和V(見§操作名稱替代名稱)。V作戰​​遞增信號量小號和運行時的P 減它。
該信號量的值小號是當前可用的資源的單位數。P操作浪費時間或休眠直到由信號量保護的資源變得可用時,在該時間資源被立即權利。在V操作是相反:它使一個資源可用後再次進程已使用完畢。信號中的一個重要屬性小號是不能除通過用V和P的操作而改變其值。
一個簡單的方法來了解等待(P)和信號(V)的操作是:
等待:如果信號量變量的值不爲負,減1它如果信號量的變量是現在否定的,則處理執行等待被阻塞(即,加到信號量的隊列),直到值大於或等於1。否則,過程繼續執行,具有所使用的資源的單位。
信號:遞增1信號量變量的值的增加後,如果預先遞增值爲負(意味着有等待資源的進程),其傳送從所述信號量的等待隊列到就緒隊列中的阻塞的進程。
許多操作系統都提供了一個解除阻止等待的過程時,信號量遞增有效信號元。這意味着,過程不浪費不必要的時間檢查信號量的值。
計數信號量的概念可與權利要求或信號量,在實現技術返回多個“單位”的能力進行擴展的Unix。

爲了避免飢餓,信號量有一個相關的隊列中的進程(通常與FIFO語義)。如果一個過程在具有零值信號量進行P動作,則處理被添加到信號燈的隊列和它的執行被掛起。當其它處理而執行爲V操作遞增信號,和有在隊列過程,它們中的一個從隊列中刪除,並恢復執行。當方法具有不同的優先級隊列可以通過優先排序,使得最高優先級的處理被從隊列中取出第一。
如果實現不保證遞增,遞減和比較操作的原子,再有就是被遺忘遞增或遞減的風險,或信號量的值成爲負數。原子可以通過使用機器指令,能夠實現讀取,修改和寫入在單個操作中的信號量。在沒有這種硬件的指令,一個原子操作可通過使用一個來合成軟件互斥算法。在單處理器系統中,原子操作可以暫時中止確保搶佔或禁用硬件中斷。其中,它有可能爲兩個程序共用信號在同一時間在不同的處理器上運行該方法不多處理器系統上工作。爲了解決這個問題,在一個多處理器系統中的鎖定變量可以用來控制訪問信號量。鎖定變量是用操縱的測試和設置鎖命令。


信號量與互斥
一個互斥基本上是同樣的事情當作二元信號燈,有時使用相同的基本實現。它們之間的差異是在如何使用它們。而二進制信號可被用作一個互斥,互斥是一個更具體的用例,在只有該鎖定互斥的處理是應該解鎖。這種約束使得有可能實現互斥一些額外的功能:
1.因爲只有鎖定互斥體的過程中應該打開它,一個互斥體可以存儲過程中的鎖定它的ID,並確認相同的過程解鎖。
2.互斥體可以提供優先級反轉的安全性。如果互斥知道誰鎖住它,應該打開它,就可以當一個高優先級任務開始等待互斥體,以促進這一進程的優先級。
3.互斥鎖還可以提供安全的缺失,其中過程持有互斥不會被意外刪除。
4.或者,如果該過程保持互斥被刪除(可能是由於不可恢復的錯誤),則互斥可以自動釋放。

5.互斥可以是遞歸的:一個進程被允許多次鎖定,而不會造成死鎖。


在 Linux 下,PV 操作通過調用semop函數來實現。該函數定義在頭文件 sys/sem.h中,原型如下:
int semop(int semid,struct sembuf *sops,size_t nsops);


在 Linux 下,PV 操作通過調用semop函數來實現。該函數定義在頭文件 sys/sem.h中,原型如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout);
參數
semid:信號集的識別碼,可通過semget獲取。
sops:指向存儲信號操作結構的數組指針,信號操作結構的原型如下

struct sembuf
{
unsigned short sem_num; /* semaphore number */
short sem_op; /* semaphore operation */
short sem_flg; /* operation flags */
};


這三個字段的意義分別爲:
sem_num:操作信號在信號集中的編號,第一個信號的編號是0。
sem_op:如果其值爲正數,該值會加到現有的信號內含值中。通常用於釋放所控資源的使用權;如果sem_op的值爲負數,而其絕對值又大於信號的現值,操作將會阻塞,直到信號值大於或等於sem_op的絕對值。通常用於獲取資源的使用權;如果sem_op的值爲0,則操作將暫時阻塞,直到信號的值變爲0。
sem_flg:信號操作標誌,可能的選擇有兩種
IPC_NOWAIT //對信號的操作不能滿足時,semop()不會阻塞,並立即返回,同時設定錯誤信息。

SEM_UNDO //程序結束時(不論正常或不正常),保證信號值會被重設爲semop()調用前的值。這樣做的目的在於避免程序在異常情況下結束時未將鎖定的資源解鎖,造成該資源永遠鎖定。

nsops:信號操作結構的數量,恆大於或等於1。
timeout:當semtimedop()調用致使進程進入睡眠時,睡眠時間不能超過本參數指定的值。如果睡眠超時,semtimedop()將失敗返回,並設定錯誤值爲EAGAIN。如果本參數的值爲NULL,semtimedop()將永遠睡眠等待。
返回說明
成功執行時,兩個系統調用都返回0。失敗返回-1,errno被設爲以下的某個值
E2BIG:一次對信號的操作數超出系統的限制
EACCES:調用進程沒有權能執行請求的操作,並且不具有CAP_IPC_OWNER權能
EAGAIN:信號操作暫時不能滿足,需要重試
EFAULT:sops或timeout指針指向的空間不可訪問
EFBIG:sem_num指定的值無效
EIDRM:信號集已被移除
EINTR:系統調用阻塞時,被信號中斷
EINVAL:參數無效
ENOMEM:內存不足
ERANGE:信號所允許的值越界
發佈了72 篇原創文章 · 獲贊 19 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章