#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>/* * key:返回的 ID 与 key 有关系 * nsems:信号量的值 * semflg:创建标记 * return:成功返回信号量 ID,失败返回 -1,并设置 erron */int semget(key_t key, int nsems, int semflg);#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>/* * semid:信号量 ID * sops:对信号量的操作 * nsops:要操作的信号数量 * return:成功返回 0,失败返回 -1,并设置 erron */int semop(int semid, struct sembuf *sops, size_t nsops);struct sembuf { /* 信号量的个数,除非使用多个信号量,否则设置为 0 */ unsigned short sem_num; /* 信号量的操作,-1 表示 p 操作,1 表示 v 操作 */ short sem_op; /* 通常设置为 SEM_UNDO,使得 OS 能够跟踪信号量并在没有释放时自动释放 */ short sem_flg; };#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>/* * semid:要设置的信号量 ID * semnum:要设置的信号量的个数 * cmd:设置的属性 */int semctl(int semid, int semnum, int cmd, ...);union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */};// 创建或获取一个信号量int sem_get(int sem_key) { int sem_id = semget(sem_key, 1, IPC_CREAT | 0666); if (sem_id == -1) { printf("sem get failed.\n"); exit(-1); } else { printf("sem_id = %d\n", sem_id); return sem_id; }}// 初始化信号量int set_sem(int sem_id) { union semun sem_union; sem_union.val = 1; if(semctl(sem_id, 0, SETVAL, sem_union) == -1) { fprintf(stderr, "Failed to set sem\n"); return 0; } return 1; } void del_sem(int sem_id) { union semun sem_union; if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1) fprintf(stderr, "Failed to delete sem, sem has been del.\n"); }// 减 1,加锁,P 操作void sem_down(int sem_id) { if (-1 == semop(sem_id, &sem_lock, 1)) fprintf(stderr, "semaphore lock failed.\n");}// 加 1,解锁,V 操作void sem_up(int sem_id) { if (-1 == semop(sem_id, &sem_unlock, 1)) fprintf(stderr, "semaphore unlock failed.\n");}int main(int argc, char **argv) { int sem_id = sem_get(12); // 第一次调用多加一个参数,第二次调用不加参数,仅在第一次调用时创建信号量 if (argc > 1 && (!set_sem(sem_id))) { printf("set sem failed.\n"); return -1; } // P 操作 sem_down(sem_id); printf("sem lock...\n"); printf("do something...\n"); sleep(10); // V 操作 sem_up(sem_id); printf("sem unlock...\n"); // 第二次调用后删除信号量 if (argc == 1) del_sem(sem_id); return 0;}