1. #include <sys/types.h>
    2. #include <sys/ipc.h>
    3. #include <sys/sem.h>
    4. /*
    5. * key:返回的 ID 与 key 有关系
    6. * nsems:信号量的值
    7. * semflg:创建标记
    8. * return:成功返回信号量 ID,失败返回 -1,并设置 erron
    9. */
    10. int semget(key_t key, int nsems, int semflg);
    11. #include <sys/types.h>
    12. #include <sys/ipc.h>
    13. #include <sys/sem.h>
    14. /*
    15. * semid:信号量 ID
    16. * sops:对信号量的操作
    17. * nsops:要操作的信号数量
    18. * return:成功返回 0,失败返回 -1,并设置 erron
    19. */
    20. int semop(int semid, struct sembuf *sops, size_t nsops);
    21. struct sembuf {
    22. /* 信号量的个数,除非使用多个信号量,否则设置为 0 */
    23. unsigned short sem_num;
    24. /* 信号量的操作,-1 表示 p 操作,1 表示 v 操作 */
    25. short sem_op;
    26. /* 通常设置为 SEM_UNDO,使得 OS 能够跟踪信号量并在没有释放时自动释放 */
    27. short sem_flg;
    28. };
    29. #include <sys/types.h>
    30. #include <sys/ipc.h>
    31. #include <sys/sem.h>
    32. /*
    33. * semid:要设置的信号量 ID
    34. * semnum:要设置的信号量的个数
    35. * cmd:设置的属性
    36. */
    37. int semctl(int semid, int semnum, int cmd, ...);
    38. union semun {
    39. int val; /* Value for SETVAL */
    40. struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
    41. unsigned short *array; /* Array for GETALL, SETALL */
    42. };
    43. // 创建或获取一个信号量
    44. int sem_get(int sem_key) {
    45. int sem_id = semget(sem_key, 1, IPC_CREAT | 0666);
    46. if (sem_id == -1) {
    47. printf("sem get failed.\n");
    48. exit(-1);
    49. } else {
    50. printf("sem_id = %d\n", sem_id);
    51. return sem_id;
    52. }
    53. }
    54. // 初始化信号量
    55. int set_sem(int sem_id) {
    56. union semun sem_union;
    57. sem_union.val = 1;
    58. if(semctl(sem_id, 0, SETVAL, sem_union) == -1) {
    59. fprintf(stderr, "Failed to set sem\n");
    60. return 0;
    61. }
    62. return 1;
    63. }
    64. void del_sem(int sem_id) {
    65. union semun sem_union;
    66. if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
    67. fprintf(stderr, "Failed to delete sem, sem has been del.\n");
    68. }
    69. // 减 1,加锁,P 操作
    70. void sem_down(int sem_id) {
    71. if (-1 == semop(sem_id, &sem_lock, 1))
    72. fprintf(stderr, "semaphore lock failed.\n");
    73. }
    74. // 加 1,解锁,V 操作
    75. void sem_up(int sem_id) {
    76. if (-1 == semop(sem_id, &sem_unlock, 1))
    77. fprintf(stderr, "semaphore unlock failed.\n");
    78. }
    79. int main(int argc, char **argv) {
    80. int sem_id = sem_get(12);
    81. // 第一次调用多加一个参数,第二次调用不加参数,仅在第一次调用时创建信号量
    82. if (argc > 1 && (!set_sem(sem_id))) {
    83. printf("set sem failed.\n");
    84. return -1;
    85. }
    86. // P 操作
    87. sem_down(sem_id);
    88. printf("sem lock...\n");
    89. printf("do something...\n");
    90. sleep(10);
    91. // V 操作
    92. sem_up(sem_id);
    93. printf("sem unlock...\n");
    94. // 第二次调用后删除信号量
    95. if (argc == 1)
    96. del_sem(sem_id);
    97. return 0;
    98. }