int semget(key_t key, int num_sems, int sem_flags);
int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);
sem_id是由semget返回的信號量標識符,sembuf結構的定義以下:函數
struct sembuf{ short sem_num;//除非使用一組信號量,不然它爲0 short sem_op;//信號量在一次操做中須要改變的數據,一般是兩個數,一個是-1,即P(等待)操做, //一個是+1,即V(發送信號)操做。 short sem_flg;//一般爲SEM_UNDO,使操做系統跟蹤信號, //並在進程沒有釋放該信號量而終止時,操做系統釋放信號量 };
int semctl(int sem_id, int sem_num, int command, ...);
若是有第四個參數,它一般是一個union semum結構,定義以下:spa
union semun{ int val; struct semid_ds *buf; unsigned short *arry; };
#include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <sys/sem.h> static int sem_id = 0; static int init_sem() { semun sem_union; sem_union.val = 1; if (semctl(sem_id, 0, SETVAL, sem_union) == -1) { printf("error to open semaphore!\n"); return 0; } return 1; } static int del_sem() { semun sem_union; if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1) { printf("err to delete semaphore!\n"); return 0; } return 1; } static int semaphore_p() { sembuf sem_buf; sem_buf.sem_num = 0; sem_buf.sem_op = -1; sem_buf.sem_flg = SEM_UNDO; if (semop(sem_id, &sem_buf, 1) == -1) { printf("semaphore failed\n"); return 0; } return 1; } static int semaphore_v() { sembuf sem_buf; sem_buf.sem_num = 0; sem_buf.sem_op = 1; sem_buf.sem_flg = SEM_UNDO; if (semop(sem_id, &sem_buf, 1) == -1) { printf("semaphore failed\n"); return 0; } return 1; } int main(int argc, char* argv[]) { char message = 'X'; sem_id = semget((key_t)1234, 1, 0666|IPC_CREAT); if (argc > 1) { if (!init_sem()) { printf("create semaphore failed\n"); exit(EXIT_FAILURE); } message = 'F'; sleep(3); } for (int i = 0; i < 10; i++) { if (!semaphore_p()) { exit(EXIT_FAILURE); } printf("%c", message); fflush(stdout); sleep(rand()%3 ); printf("%c", message); fflush(stdout); sleep(rand()%2); if (!semaphore_v()) { exit(EXIT_FAILURE); } sleep(rand()%2); } sleep(10); printf("\n %d- finished\n", getpid()); if (argc > 1) { sleep(3); del_sem(); } exit(EXIT_FAILURE); return 0; }
須要注意,執行的方法:操作系統
brackendeMacBook-Pro:cpp_test bracken$ gcc -o selm.exe main.cpp -lm brackendeMacBook-Pro:cpp_test bracken$ ./selm.exe 0 & ./selm.exe [1] 10796 XXFFXXXXFFFFXXFFXXXXFFXXFFXXFFXXFFXXFFFF 10797- finished brackendeMacBook-Pro:cpp_test bracken$ 10796- finished
例子分析 :同時運行一個程序的兩個實例,注意第一次運行時,要加上一個字符做爲參數,例如本例中的字符‘O’,它用於區分是否爲第一次調用,同時這個字符輸出到屏幕中。由於每一個程序都在其進入臨界區後和離開臨界區前打印一個字符,因此每一個字符都應該成對出現,正如你看到的上圖的輸出那樣。在main函數中循環中咱們能夠看到,每次進程要訪問stdout(標準輸出),即要輸出字符時,每次都要檢查信號量是否可用(即stdout有沒有正在被其餘進程使用)。因此,當一個進程A在調用函數semaphore_p進入了臨界區,輸出字符後,調用sleep時,另外一個進程B可能想訪問stdout,可是信號量的P請求操做失敗,只能掛起本身的執行,當進程A調用函數semaphore_v離開了臨界區,進程B立刻被恢復執行。而後進程A和進程B就這樣一直循環了10次。線程