用a表示發往北京的貨物,用b表示發往上海的貨物,分別使用兩個訊號量來代表兩類貨物的數量。
posix訊號量的pv操作為原子操作(atomic operation),不會因cpu的排程而被打斷。用兩個程序分別模擬送貨員,不斷運出貨物,即不斷進行p操作,當貨物數量為0,即訊號量值為0時等待。用乙個程序模擬收貨員,不斷放入貨物,即不斷對兩個訊號量進行p操作。
但是實際生產中庫存都是有限的,因此我們設兩種貨物的最大庫存為20,當達到最大庫存時,不再進行生產。初始庫存為10。
在經典的生產者-消費者問題中,我們可以看到如下偽**:
// 生產者
while(1
)// 消費者
while(1
)
其中full和empty都是訊號量,pv操作為對訊號量的值進行減加。full表示可用貨物,empty表示可用的空餘空間,二者之和為倉庫容量。如果在本問題中,即有乙個收貨員放入兩種貨物到兩個不同區域,如果還使用這種方式,就會造成當一種貨物空餘空間不足時,就會導致程式阻塞,即另一種貨物也無法放入它的倉庫。
因此,收貨員使用以下形式的偽**:
while(1
)if(full2 < buffer_size2)
}
使用posix訊號量時,p和v都是原子操作,因此p(empty)是不可被打斷的,保證了empty的值時最新的。如果我們使用 if(full < buffer_size) ,獲取full值之後可能被會切換到其他程序,導致做比較時full值不是最新的,可能已經是其他程序修改過的。
但是這種情況在這個問題中沒有影響,因為v(full)是原子操作,不會造成full的值混亂。雖然可能會出現以下情況:獲取到的full值為20,buffer_size為20,但是在比較時,full1的實際值已經變成了19,所以本來應該要執行v(full)的,但不會執行。這造成了邏輯上的瑕疵,但對整體執行是沒有影響的,因為不會造成倉庫溢位。如果想解決這裡的問題,我們可以對比較語句加上臨界區保護,即在比較完成前,不允許其他程序對訊號量進行修改。
因為只有乙個收貨員,我們假設優先處理貨物a,貨物a和貨物b每次放入倉庫需要0.6s,送貨員每次拿出需要0.5s。
程式寫好後,實驗時有多種方式,比如再寫個程式,在其中通過fork啟動各個編譯好的程式,或者是寫乙個shell指令碼,每個程式後台執行,將各自的輸出重定向到文字檔案。我實驗時為了方便,選擇了直接開3個shell,在其中分別啟動3個程式。
首先啟動收貨員程式producer.out,如下圖,在達到最大庫存時,兩種貨物都停止了放入。
之後先啟動第乙個送貨員程式consumer1 .out,此時producer.out程式的輸出如下圖,可以發現只有a在變化。
最後啟動第二個送貨員程式consumer2.out,此時貨物b的數量也發生了變化。
等待一段時間後,可以發現a和b數量都變成了0,因為設定的收貨速度大於送貨速度。
/* 使用ctrl-c終止程序後,訊號量雖然很close,但不會unlink,
也就訊號量的值依然儲存在核心中,因此寫了個程式來重置訊號量的值。
*/#include
#include
#include
#include
#define sem_a "goods_a"
#define sem_b "goods_b"
intmain()
感慨一下,自從寫好了乙個makefile之後,每次用到makefile時在之前基礎上稍微改改就行了。
# makefile
## date: october 16, 2018
# author: yan he
cc = gcc # the compiler
# inc_src = $(wildcard ./lib/*.c ./include/src/*.c) # get all "*.c" file in lib and include
# includes = -i ./include -i . #the path to find included file
libs = -l ./lib # the path to find library file
ccflags = -lpthread -g -wall -o0 #the needed flag. if the vesion is release, '-g' need to be removed.
all:$(targets)
$(targets):%.out:%.c
@ echo cxx/ld -o $@ $<
@ $(cc) $^ $(ccflags) -o $@
clean:
rm -rf *.out *.o $(targets)
.phony:clean
systemV訊號量 與 Posix訊號量
一 函式上的區別 訊號量有兩種實現 傳統的system v訊號量和新的posix訊號量。它們所提供的函式很容易被區分 對於所有system v訊號量函式,在它們的名字裡面沒有下劃線。例如,應該是semget 而不是sem get 然而,所有的的posix訊號量函式都有乙個下劃線。下面列出了它們提供的...
posix訊號量機制
posix為可移植的作業系統介面標準,定義了作業系統應該為應用程式提供的介面標準 訊號量機制是我們在作業系統中學到的知識,可以用來解決同步和互斥的問題,它只能被兩個標準的原語wait s 和signal s 來訪問,也就是p操作和v操作。訊號量的概念在system v 和posix 中都有,但是它們...
程序間通訊之Posix 訊號量
概述 訊號量 semaphore 是一種用於提供不同程序間或者乙個給定程序的不同執行緒間同步手段的原語。1.posix 有名訊號量 使用posix ipc 名字標識,可用於程序或執行緒間的同步。2.posix 基於記憶體的訊號量 存放在共享記憶體區中,可用於程序或執行緒間的同步。我們暫時只考慮不同程...