各位看官們,大家好,上一回中咱們說的是使用信號量進行進程間同步與互斥的例子,這一回咱們繼續說該例子。閒話休提,言歸正轉。讓我們一起talk C栗子吧!
看官們,我們在上一回中介紹了信號量相關的函數及其用法,這一回中我們通過具體的例子來說明如使用這些函數來操作信號量。
下面是具體的使用步驟:
1.使用semget函數創建一個信號量; 2.使用semctl函數初始化信號量; 3.使用semop函數對信號量進行P操作,以便進程進入臨界區操作臨界資源; 4.使用semop函數對信號量進行V操作,以便進程離開臨界區時喚醒其它進程; 5..使用semctl函數刪除信號量;大家還記得我們在前面章回中的偽代碼吧,我們將把這些偽代碼轉換為實際的C語言代碼:
nocritical code //非臨界區的代碼
P(sem); //執行P操作,進入臨界區,執行臨界區中的代碼
{
critical code; //臨界區代碼
do something
}
V(sem); //執行V操作,離開臨界區
nocritical code //非臨界區的代碼
看官們,正文中就不寫代碼了,詳細的代碼放到了我的資源中,大家可以下載使用。
另外,我說一下代碼中的內容(可以下載代碼後對比著看):代碼開始處自己定義了聯合體semun,不然會有編譯錯誤,詳細如下:
union semun
{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO */
};
代碼中對信號量的操作都進行了封裝,比如把semctl函數封裝成了初始化和刪除信號量的函數,把semop函數封裝成了信號量的P/V操作。此外,我們在代碼中對使用參數和不使用參數這兩種情況進行了區分,而且在使用參數時對程序進行了延時操作,這樣是為了方便大家觀察程序運行結果。
下面是程序的運行結果,請大家參考:
(在運行程序時使用-s參數表示對信號量進行初始化和刪除操作,不使用參數時只進行P/V操作。)
$./a -s & //在後台運行編譯後的程序a,參數-s表示初始化或者刪除信號量
[1] 2713 //程序在後台運行,這裡啟動了後台進程,PID:2713
$ [pid: 2713 ] init semaphore
[pid: 2713 ] running nocritical code
$./a //在前台運行程序,不使用任何參數,這裡啟動了前台進程,PID:2714
[pid: 2714 ] running nocritical code
[pid: 2713 ] enter critical area
[pid: 2713 ] running critical code //後台進程執行臨界區的代碼
[pid: 2713 ] leave critical area
[pid: 2714 ] enter critical area
[pid: 2714 ] running critical code //前台進程執行臨界區的代碼
[pid: 2714 ] leave critical area
[pid: 2714 ] running nocritical code
$ [pid: 2713 ] delete semaphore
[pid: 2713 ] running nocritical code
//需要按下回車鍵切換到終端窗口中
[1]+ Done ./a -s //後台進程運行結束
大家從上面的運行結果中可以看到,首先是後台進程執行臨界區中的代碼,然後才是前台進程執行臨界區中的代碼。也就是說同一段時間內只能有一個進程操作臨界區的代碼,這便是進程之間的同步與互斥。
各位看官,關於使用信號量進行進程間同步與互斥的例子咱們就說到這裡。欲知後面還有什麼例子,且聽下回分解 。