unix XSI IPC-信号量同步例程
admin
2023-02-04 19:00:04
0次

原理不多讲,可能查看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.  
  9. int open_semque(void); 
  10. void set_sem(int, int); 
  11. #if 1 

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



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.  
  9. void v_sem(int); 
  10. void p_sem(int); 
  11. int open_semque(void); 
  12. void set_sem(int, int); 
  13. #if 1 
  14. union semun 
  15. { 
  16.       int val; 
  17.       struct semid_ds buf; 
  18.       unsigned short *array; 
  19. }; 
  20.  
  21. #endif 
  22.  
  23.  
  24. int main(int argc,char** argv) 
  25. { 
  26.       int ret; 
  27.        
  28.       int semque_id; 
  29.       semque_id = open_semque(); 
  30.         
  31.       //set_sem(semque_id, 1); 
  32.       ret = semctl(semque_id, 0, GETVAL); 
  33.       printf("信号集中第一个信号量的值为:%d\n",ret); 
  34.        
  35.       fputs("执行操作V\n",stdout); 
  36.        
  37.       v_sem(semque_id); 
  38.       ret = semctl(semque_id, 0, GETVAL); 
  39.       printf("信号集中第一个信号量的值为:%d\n",ret); 
  40.        
  41.       int second = 10; 
  42.       while(second) 
  43.       { 
  44.             sleep(1); 
  45.             printf("%ds\n",second); 
  46.             ret = semctl(semque_id, 0, GETVAL); 
  47.             printf("信号集中第一个信号量的值为:%d\n",ret); 
  48.             second--; 
  49.       } 
  50.        
  51.  
  52.        
  53.       fputs("执行操作P\n",stdout); 
  54.       p_sem(semque_id); 
  55.       ret = semctl(semque_id, 0, GETVAL); 
  56.       printf("信号集中第一个信号量的值为:%d\n",ret); 
  57.  
  58.       //semctl(semque_id, 0, IPC_RMID); 
  59.  
  60.       return 0; 
  61. } 
  62.  
  63.  
  64. int open_semque(void) 
  65. { 
  66.       key_t key = ftok("./",100); 
  67.        
  68.       if(key == -1) 
  69.       { 
  70.             perror("ftok\n"); 
  71.             exit(1); 
  72.       } 
  73.        
  74.       int semque_id = semget(key, 1,IPC_CREAT|0666); 
  75.       if(semque_id  == -1) 
  76.       { 
  77.             perror("msgget\n"); 
  78.             exit(1); 
  79.       } 
  80.        
  81.       return semque_id; 
  82. } 
  83.  
  84. void set_sem(int semque_id, int val) 
  85. { 
  86.       union semun sem_union; 
  87.        
  88.       sem_union.val = val; 
  89.        
  90.      if(semctl(semque_id, 0, SETVAL, sem_union) == -1) 
  91.      { 
  92.             perror("semctl_set\n"); 
  93.             exit(1);      
  94.      } 
  95. } 
  96.  
  97. void p_sem(int semque_id) 
  98. { 
  99.       struct sembuf arry[1]; 
  100.       arry[0].sem_num = 0; 
  101.       arry[0].sem_op = 1; 
  102.       //arry[0].sem_flg = SEM_UNDO; 
  103.        
  104.       int ret; 
  105. //需要通过结构体struct sembuf进行赋值       
  106.       if(ret = semop(semque_id, arry, 1)) 
  107.       { 
  108.             perror("semop\n"); 
  109.             exit(1);        
  110.       } 
  111.  
  112. } 
  113.  
  114. void v_sem(int semque_id) 
  115. { 
  116.       struct sembuf arry[1]; 
  117.       arry[0].sem_num = 0; 
  118.       arry[0].sem_op = -1; 
  119.       //arry[0].sem_flg = IPC_NOWAIT; 
  120.       arry[0].sem_flg = SEM_UNDO; 
  121.        
  122.       int ret; 
  123.        
  124.       if(ret = semop(semque_id, arry, 1)) 
  125.       { 
  126.             perror("semop\n"); 
  127.             exit(1);        
  128.       } 
  129. } 

 

相关内容

热门资讯

空调连续工作多久需要停机休息 空调连续工作的时间取决于多个因素,包括空调的型号、功率、使用环境和维护情况等。一般来说,空调可以连续...
空调哪个符号是除湿的 空调除湿功能通常用一个水滴形状的符号表示。不同品牌和型号的空调遥控器可能会有所差异,但一般来说,除湿...
格力空调多长时间加一次氟利昂 1、一般情况下,空调对氟利昂的使用量是非常小的,所以在空调使用了四年左右的时候再考虑加也没问题。2、...
空调用多长时间需要加氟一次 一般情况下是五年。当出现以下这几种情况时,空调才需要加氟。1、空调的室内机和室外机各有两个接口,当接...
格调生活·C标思享荟:卡萨帝在... 9月12日的郑州龙湖金融岛,夜风轻拂,灯光璀璨。“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑...
品牌价值破千亿、高端份额持续领... 9月12日,“C标时刻共传奇——卡萨帝思享荟暨20周年品牌盛典郑州站”在郑州龙湖金融岛举办。2026...
空调主板坏了修800还是换新的 空调主板坏了是修还是换新,需要考虑多个因素,以下是一些建议:1. 维修成本:如果维修费用较低,比如 ...
空调开多久需要休息多长时间 问题:空调开多久需要休息多长时间回答:1、在使用空调的过程中,一般空调开7~8个小时左右需要休息2~...
中央空调多长时间清洗一次 1、一般空调开机前清洗一次即可,空调开机中间时段再清洗一次,空调关机时清洗一次,这样比较合理。2、空...
中央空调氟利昂多久加一次 看空调制热和制冷程度,很多人的观点认为氟利昂必须一年放一次,其实这个观点是错误的,理解上面有点偏差,...