訊號量就是具有原子性的計數器,就相當於一把鎖,在每個程序要訪問臨界資源時,必須要向訊號量拿個鎖」,它才能進去臨界資源這個「房間」,並鎖上門,不讓其他程序進來,此時訊號量執行p()操作,鎖的數目減少了乙個,所以計數器減1,;當它訪問完成時,它出來,將鎖還給訊號量,執行v()操作,計數器加1;該函式用來建立乙個新訊號量,其定義為:int semget(key_t key, int num, int sem_flags)
key是整數值,程式對所有訊號量的訪問都是間接的,先提供乙個鍵,再由系統生成乙個訊號量識別符號。num_sem引數指定需要的訊號量數目,一般取1;sem_flags引數是一組標誌。
semget函式在成功時返回乙個正數,也就是其他訊號量函式用到的訊號量識別符號,失敗時返回-1.
定義為:int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops)
sem_id 表示訊號量識別符號,semops指向乙個結構陣列的指標,每個陣列元素至少包含以下幾個成員:
struct sembuf
定義為:int semctl(int sem_id, int sem_num, int command,…)
sem_id:表示訊號量識別符號,sem_num表示訊號量編號一般取0,command引數是將要採取的行動,如:setval:用來把訊號量初始化為乙個已知的值,作用就是在訊號量第一次使用前對它進行設定。ipc_rmid用於刪除乙個不再繼續使用的訊號量識別符號。如果還有第四個引數,它是乙個union semun結構(該聯合結構可能需自己定義,可通過查閱semctl的手冊檢視是否給出了該定義)
union semun
讓兩個程序分別向顯示器(linux下一切皆檔案,臨界資源)列印aa和bb,當沒有訊號量進行保護時,會出現資料混亂,例如:「aabbabaaab…」,為了解決這一問題,我們建立訊號量進行保護。列印「aa」或「bb」
vi sem.c
#include#include#include#includeunion semun;
static int set_semvalue(void);
static void del_semvalue(void);
static int semaphore_p(void);
static int semaphore_v(void);
static int sem_id;
int main(int argc, char *ar**)
op_char = 'x';
sleep(2);
}/*進入和離開臨界區10次,每次迴圈開始的時候首先呼叫semaphore_p函式,它在程式將進入臨界區域時設定訊號量以等待進入*/
for(i=0; i<10; i++)
printf("\n%d - finished\n", getpid());
if (argc > 1)
exit(exit_success);
}/*該函式用來將semctl呼叫的command引數設定為setval來初始化訊號量*/
static int set_semvalue(void)
/*通過呼叫semctl呼叫的command設定為ipc_rmid來刪除訊號量id*/
static void del_semvalue(void)
/*對訊號量執行減1操作*/
static int semaphore_p(void)
return(1);
}/*對訊號量執行加1操作*/
static int semaphore_v(void)
return(1);
}
編譯執行
與上述**幾乎相同,只不過變為了父子程序間的訊號量機制。
vi sem2.c
#include#include#include#include#include#includestatic int set_semvalue(void);
static void del_semvalue(void);
static int semaphore_p(void);
static int semaphore_v(void);
static int sem_id;
union semun;
int main(int argc, char *ar**)
else if (id>0)
op_char = 'x';
sleep(2);
}for(i=0; i<10; i++)
printf("\n%d - finished\n", getpid());
if (id> 0)
exit(exit_success);
}static int set_semvalue(void)
static void del_semvalue(void)
static int semaphore_p(void)
return(1);
}static int semaphore_v(void)
return(1);
}
編譯執行結果:
注意:在這裡我們可以看到子程序的pid為父程序的pid+1,注意的是fork建立子程序的返回值為0,和這裡的pid是不同的。
參考:linux程式設計第四版
程序間通訊之訊號量
訊號量的本質是一種資料操作鎖,其本身不具有資料交換的能力,而是通過控制其他的通訊資源 檔案 外部裝置 來實現程序間通訊,它本身只是一種外部資源的標識。訊號量在此過程中負責資料的互斥 同步等功能。當請求乙個訊號量來表示資源時,程序需要讀取訊號量的值來判斷資源是否可用。大於0,資源可以請求,等於0,無資...
程序間通訊之訊號量
訊號量的本質是一種資料操控鎖,它本身不具有資料交換的功能,而是通過來控制其他的通訊資源來實現程序間通訊的,訊號主要負責資料的同步與互斥功能。程序請求乙個使用訊號量來表示的資源時,首先要讀取訊號量的值來判斷資源是否能被使用,若訊號量的值大於0,資源可用,等於0,無資源可用,同時程序會進入睡眠狀態,直到...
程序間通訊之 訊號量
訊號量相當於記錄資源能同時被多少個程序訪問。訊號量的作用 程序間同步控制。訊號量有乙個初值,每當有程序申請使用訊號量,就會通過乙個p操作對訊號量進行 1操作,當計數器減到0的時候就說明沒有資源了,其他程序要想訪問就必須等待,當該程序執行完這段工作之後,就會執行v操作,即對訊號量進行 1操作。標頭檔案...