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次。线程