unixXSIIPC-信号量同步例程

原理不多讲,可能查看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  
  2. #include  
  3. #include  
  4. #include  
  5. #include  
  6. #include  
  7. #include  
  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  
  2. #include  
  3. #include  
  4. #include  
  5. #include  
  6. #include  
  7. #include  
  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. } 

 


新闻名称:unixXSIIPC-信号量同步例程
当前路径:http://www.xwwzsj.com/article/gscoec.html

其他资讯

售后响应及时

7×24小时客服热线

数据备份

更安全、更高效、更稳定

价格公道精准

项目经理精准报价不弄虚作假

合作无风险

重合同讲信誉,无效全额退款