千家信息网

unix XSI IPC-信号量同步例程

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,原理不多讲,可能查看unix 高级环境编程,只提一些注意点信号量系统限制信号量最大值 32767最多信号量集 128每个集中最多含有250信号量难理解的是标志位SEM_UNDO以下是个人愚见:首先是了
千家信息网最后更新 2026年11月01日unix XSI IPC-信号量同步例程

原理不多讲,可能查看unix 高级环境编程,只提一些注意点

信号量系统限制

  • 信号量最大值 32767
  • 最多信号量集 128
  • 每个集中最多含有250信号量

难理解的是标志位SEM_UNDO

以下是个人愚见:

首先是了解一下"信号量调整值",每一个信号量都会对应有一个调整值,并且对信号量进行操作的时候进行维护。如果设置了SEM_UNDO则立即更新,如果没有何时更新,我也不知道,可能是系统调度吧;

在进行退出,无论是正常还是异常,内核都会遍历一次进程的调整值,进行处理,具体怎样处理有待研究;

个人经验:如果在V 和 P 操作上, 如果需要阻塞的,最好标志位上赋SEM_UNDO,如果不阻塞那就不需要,这样会少点意想不到的错误

网上解释:

每一个独立的信号灯操作可能都需要维护一个调整动作。 Linux 至少为每一个进程

的每一个信号灯数组都维护一个 sem_undo 的数据结构。如果请求的进程没有,就在需 要的时候为它创建一个。这个新的 sem_undo 数据结构同时在进程的 task_struct 数据 结构和信号灯队列的 semid_ds 数据结构的队列中排队。对信号灯队列中的信号灯执行 操作的时候,和这个操作值相抵消的值加到这个进程的 sem_undo 数据结构的调整队列 这个信号灯的条目上。所以,如果操作值为 2 ,那么这个就在这个信号灯的调整条目上 增加 -2 。        当进程被删除,比如退出的时候, Linux 遍历它的 sem_undo 数据结构组,并 实施对于信号灯数组的调整。如果删除信号灯,它的 sem_undo 数据结构仍旧停留在进 程的 task_struct 队列中,但是相应的信号灯数组标识符标记为无效。这种情况下,清除 信号灯的代码只是简单地废弃这个 sem_undo 数据结构。

http://3521632.blog.163.com/blog/static/110237933201032041353708/


以下例程

第一:先执行init.c初始化,让信号量集的第1个信号量值为1,当然电脑索引是从0开始的;

第二:再执行多个test.c



intit.c


  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. int open_semque(void);
  9. void set_sem(int, int);
  10. #if 1

  11. union semun
  12. {
  13. int val;
  14. struct semid_ds buf;
  15. unsigned short *array;
  16. };
  17. #endif
  18. int main(int argc,char** argv)
  19. {
  20. int ret;
  21. int semque_id;
  22. semque_id = open_semque();
  23. set_sem(semque_id, 1);
  24. ret = semctl(semque_id, 0, GETVAL);
  25. printf("信号集中第一个信号量的值为:%d\n",ret);
  26. return 0;
  27. }
  28. int open_semque(void)
  29. {
    //创建一个键
  30. key_t key = ftok("./",100);
  31. if(key == -1)
  32. {
  33. perror("ftok\n");
  34. exit(1);
  35. }
  36. //创建信号量集,
  37. //IPC_CREAT 存在则打开,不存在则新建,
  38. //0666是权限
  39. //设置这个信号量集中包含几个信号量,设为1
  40. int semque_id = semget(key, 1,IPC_CREAT|0666);
  41. if(semque_id == -1)
  42. {
  43. perror("msgget\n");
  44. exit(1);
  45. }
  46. return semque_id;
  47. }
  48. void set_sem(int semque_id, int val)
  49. {
  50. //此联合体需要自己去创建,在初始化信号量时需要这个联合体;
  51. union semun sem_union;
  52. sem_union.val = val;
  53. if(semctl(semque_id, 0, SETVAL, sem_union) == -1)
  54. {
  55. perror("semctl_set\n");
  56. exit(1);
  57. }
  58. }



test.c


  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. void v_sem(int);
  9. void p_sem(int);
  10. int open_semque(void);
  11. void set_sem(int, int);
  12. #if 1
  13. union semun
  14. {
  15. int val;
  16. struct semid_ds buf;
  17. unsigned short *array;
  18. };
  19. #endif
  20. int main(int argc,char** argv)
  21. {
  22. int ret;
  23. int semque_id;
  24. semque_id = open_semque();
  25. //set_sem(semque_id, 1);
  26. ret = semctl(semque_id, 0, GETVAL);
  27. printf("信号集中第一个信号量的值为:%d\n",ret);
  28. fputs("执行操作V\n",stdout);
  29. v_sem(semque_id);
  30. ret = semctl(semque_id, 0, GETVAL);
  31. printf("信号集中第一个信号量的值为:%d\n",ret);
  32. int second = 10;
  33. while(second)
  34. {
  35. sleep(1);
  36. printf("%ds\n",second);
  37. ret = semctl(semque_id, 0, GETVAL);
  38. printf("信号集中第一个信号量的值为:%d\n",ret);
  39. second--;
  40. }
  41. fputs("执行操作P\n",stdout);
  42. p_sem(semque_id);
  43. ret = semctl(semque_id, 0, GETVAL);
  44. printf("信号集中第一个信号量的值为:%d\n",ret);
  45. //semctl(semque_id, 0, IPC_RMID);
  46. return 0;
  47. }
  48. int open_semque(void)
  49. {
  50. key_t key = ftok("./",100);
  51. if(key == -1)
  52. {
  53. perror("ftok\n");
  54. exit(1);
  55. }
  56. int semque_id = semget(key, 1,IPC_CREAT|0666);
  57. if(semque_id == -1)
  58. {
  59. perror("msgget\n");
  60. exit(1);
  61. }
  62. return semque_id;
  63. }
  64. void set_sem(int semque_id, int val)
  65. {
  66. union semun sem_union;
  67. sem_union.val = val;
  68. if(semctl(semque_id, 0, SETVAL, sem_union) == -1)
  69. {
  70. perror("semctl_set\n");
  71. exit(1);
  72. }
  73. }
  74. void p_sem(int semque_id)
  75. {
  76. struct sembuf arry[1];
  77. arry[0].sem_num = 0;
  78. arry[0].sem_op = 1;
  79. //arry[0].sem_flg = SEM_UNDO;
  80. int ret;
  81. //需要通过结构体struct sembuf进行赋值
  82. if(ret = semop(semque_id, arry, 1))
  83. {
  84. perror("semop\n");
  85. exit(1);
  86. }
  87. }
  88. void v_sem(int semque_id)
  89. {
  90. struct sembuf arry[1];
  91. arry[0].sem_num = 0;
  92. arry[0].sem_op = -1;
  93. //arry[0].sem_flg = IPC_NOWAIT;
  94. arry[0].sem_flg = SEM_UNDO;
  95. int ret;
  96. if(ret = semop(semque_id, arry, 1))
  97. {
  98. perror("semop\n");
  99. exit(1);
  100. }
  101. }
信号 信号量 信号灯 结构 数据 数据结构 调整 进程 队列 时候 数组 个人 条目 标志 系统 联合体 处理 更新 联合 阻塞 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 朗新科技与工业互联网 金融科技创新监管互联网金融 没上市的科技互联网公司 互联网金融 金融科技 友谊互联网络科技 江苏南京365互联网科技 浙江互联网科技研学营 互联网科技革命什么开始 内蒙古九一互联网科技 翼展科技 首家互联网医院 阿里互联网科技企业 深圳无忧互联网科技 互联网科技资金流入 四川互联网展示科技馆设计 互联网科技融合创新 新氧科技和美国互联网有关系吗 陕西九四连强互联网科技有限公司 绵阳真晨互联网科技有限公司 杭州科技互联网公司有哪些 科技互联网专业务虚会材料 有马互联网科技 互联网科技美容 互联网 科技服务平台 银川新华互联网科技职业技术培训学校图片 南平创想时代互联网科技有限公司 速维有品互联网信息科技(苏州)有限公司 爱医互联网络科技 山东有哪些互联网科技公司 互联网科技圈年度人物 上海互联网科技园景观
0