#Linux#進程間通信# 信號量(semophore)

信號量本質上是一個計數器(不設置全局變量是因爲進程間是相互獨立的,而這不一定能看到,看到也不能保證++引用計數爲原子操作),可以用來控制多個進程對共享資源的訪問。它常作爲一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。主要作爲進程間以及同一進程內不同線程之間的同步和互斥手段。它和管道有所不同,它不以傳送數據爲主要目的,它主要是用來保護共享資源(信號量也屬於臨界資源),使得資源在一個時刻只有一個進程獨享。

信號量(Semaphore),有時被稱爲信號燈,是在多線程環境下使用的一種設施,是可以用來保證兩個或多個關鍵代碼段不被併發調用。在進入一個關鍵代碼段之前,線程必須獲取一個信號量;一旦該關鍵代碼段完成了,那麼該線程必須釋放信號量。其它想進入該關鍵代碼段的線程必須等待直到第一個線程釋放信號量。爲了完成這個過程,需要創建一個信號量VI,然後將Acquire Semaphore VI以及Release Semaphore VI分別放置在每個關鍵代碼段的首末端。確認這些信號量VI引用的是初始創建的信號量。

信號量的使用主要是用來保護共享資源,使得資源在一個時刻只有一個進程(線程)所擁有。爲了防止出現因多個程序同時訪問一個共享資源而引發的一系列問題,我們需要一種方法,它可以通過生成並使用令牌來授權,在任一時刻只能有一個執行線程訪問代碼的臨界區域。臨界區域是指執行數據更新的代碼需要獨佔式地執行。而信號量就可以提供這樣的一種訪問機制,讓一個臨界區同一時間只有一個線程在訪問它,也就是說信號量是用來調協進程對共享資源的訪問的。

最簡單的信號量是隻能取0和1的變量,這也是信號量最常見的一種形式,叫做二進制信號量。而可以取多個正整數的信號量被稱爲通用信號量。這裏主要討論二進制信號量。

Linux提供兩種信號量

  • (1) 內核信號量,由內核控制路徑使用 
  • (2) 用戶態進程使用的信號量,這種信號量又分爲POSIX信號量和SYSTEM V信號量。

 

內核信號量

內核信號量類似於自旋鎖,因爲當鎖關閉着時,它不允許內核控制路徑繼續進行。然而,當內核控制路徑試圖獲取內核信號量鎖保護的忙資源時,相應的進程就被掛起。只有在資源被釋放時,進程纔再次變爲可運行。只有可以睡眠的函數才能獲取內核信號量;中斷處理程序和可延遲函數都不能使用內核信號量。

內核信號量是struct semaphore類型的對象,它在<asm/semaphore.h>中定義:

/* Please don't access any members of this structure directly */
struct semaphore {
	raw_spinlock_t		lock;
	unsigned int		count;
	struct list_head	wait_list;
};

當某任務由於沒有某種條件沒有得到滿足時,它就被掛到等待隊列中睡眠。當條件得到滿足時,該任務就被移出等待隊列,此時並不意味着該任務就被馬上執行,因爲它又被移進工作隊列中等待CPU資源,在適當的時機被調度。內核信號量是在內部使用等待隊列的,也就是說該等待隊列對用戶是隱藏的,無須用戶干涉。

void down(struct semaphore *sem)
{
    unsigned long flags;

    raw_spin_lock_irqsave(&sem->lock, flags);
    if (likely(sem->count > 0))
        sem->count--;
    else
        __down(sem);//掛到等待隊列中睡眠
    raw_spin_unlock_irqrestore(&sem->lock, flags);
}

 

 

用戶態進程信號量

 

POSIX信號量

Posix是“可移植操作系統接口(Portable Operating System Interface )的首字母簡寫,但它並不是一個單一的標準,而是一個電氣與電子工程學會即IEEE開發的一系列標準,它還是由ISO(國際標準化組織)和IEC(國際電工委員會)採納的國際標準。Posix標準正變得越來越流行,很多廠家開始採用這一標準。漸漸有取代SYSTEM V信號量的趨勢。

Posix信號量是基於內存的,即信號量值是放在共享內存中的,它是由可能與文件系統中的路徑名對應的名字來標識的。

有名信號量:  放在共享內存區中由文件系統中的路徑名對應的名字來標識, 一般用於進程同步。也可以用於線程,甚至是不相關進程。類似有名管道。由於有名信號量的值是保存在文件中的,所以對於相關進程來說,子進程是繼承了父進程的文件描述符,那麼子進程所繼承的文件描述符所指向的文件是和父進程一樣的,當然文件裏面保存的有名信號量值就共享了。

無名信號量:  存放在共享內存區中,一般用於線程同步。同時也用於相關進程間的同步。也就是說,無名信號量必須是多個進程(線程)的共享變量,無名信號量要保護的變量也必須是多個進程(線程)的共享變量,這兩個條件是缺一不可的。類似無名管道。

 

SYSTEM V信號量

System v是Unix操作系統衆多版本的一個分支,它最初是由AT&T在1983年第一次發佈,System v一共有四個版本,而最成功的是System V Release 4,或者稱爲SVR4。這樣看來,一個是Unix 的標準之一(另一個標準是Open Group),一個是Unix衆多版本的分支之一(其他的分支還有Linux跟BSD)。PV操作,是狄克斯特拉荷蘭文定義的,因爲在荷蘭文中,通過叫passeren,釋放叫vrijgeven,PV操作因此得名。這是在計算機術語中不是用英語表達的極少數的例子之一。

System v信號量測試基於內核的,它放在內核裏面。

System v是信號量值的集合,而不是單個信號量。相關的信號量操作函數由<sys/ipc.h>引用。system V 信號量在內核中維護,其中包括二值信號量 、計數信號量、計數信號量集。

  • 1. 二值信號量(binary  semaphore):其值或爲0或爲1的信號量。這與互斥鎖類似,若資源被鎖住則信號量值爲0,若資源可用則信號量值爲1。
  • 2. 計數信號量(counting semaphore):其值爲0和某個限制值(對於Posix信號量,該值必須至少爲32767)之間的信號量。該信號量的值就是可用資源數。
  • 以上這兩種類型的信號中,等待(wait)操作都等待信號量的值變爲大於0,然後將它減1。掛出(post)操作則是將信號量的值加1。從而喚醒正在等待該信號量值變爲大於0的任意線程。
  • 3. 計數信號量集(set of counting semaphore):一個或者多個信號量(構成一個集合),其中每個都是計數信號量。每個集合的信號量數都存在一個限制,一般在25個的數量級。

 

信號量(semophore)分System V標準與POSIX 標準,詳細參考

#Linux#進程間通信# System V標準&POSIX標準

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章