semop SEM_UNDO标识


当操作信号量(semop)时,sem_flg可以设置SEM_UNDO标识;SEM_UNDO用于将修改的信号量值在进程正常退出(调用exit退出或main执行完)或异常退出(如段异常、除0异常、收到KILL信号等)时归还给信号量。
如信号量初始值是20,进程以SEM_UNDO方式操作信号量减2,减5,加1;在进程未退出时,信号量变成20-2-5+1=14;在进程退出时,将修改的值归还给信号量,信号量变成14+2+5-1=20。

I.SEM_UNDO示例

i.建立包含两个信号量的信号量集,第一个信号量置20,第二个信号量置10

[plain]  view plain  copy
  1. [redhat@localhost sem]$ ipcmk -S 2  
  2. Semaphore id: 131075  
  3. [redhat@localhost sem]$ ./seminfo  
  4. command : ./seminfo semid  
  5. [redhat@localhost sem]$ ./seminfo 131075  
  6. key:585c7c37  
  7. semid:131075  
  8. nsems:2  
  9. -------sem details---------  
  10. semnum:0, semval:0  
  11. semnum:1, semval:0  
  12. [redhat@localhost sem]$ ./semop  
  13. command : ./semop semid semnum semops undo[0|1] sleeps[0-15]  
  14. [redhat@localhost sem]$ ./semop 131075 0 20 0 0  
  15. [redhat@localhost sem]$ ./semop 131075 1 10 0 0  
  16. [redhat@localhost sem]$ ./seminfo 131075  
  17. key:585c7c37  
  18. semid:131075  
  19. nsems:2  
  20. -------sem details---------  
  21. semnum:0, semval:20  
  22. semnum:1, semval:10  



ii.不设置SEM_UNDO,将第一个信号量减2;进程未退出时,信号量由20变成18;进程正常退出时,保持18不变。
设置SEM_UNDO,将第二个信号量减2;进程未退出时,信号量由10变成8;进程正常退出时,将2归还给信号量,信号量重新变回10

[plain]  view plain  copy
  1. [redhat@localhost sem]$ ./semop 131075 0 -2 0 0  
  2. [redhat@localhost sem]$ ./semop 131075 1 -2 1 15 &  
  3. [1] 3339  
  4. [redhat@localhost sem]$ ./seminfo 131075  
  5. key:585c7c37  
  6. semid:131075  
  7. nsems:2  
  8. -------sem details---------  
  9. semnum:0, semval:18  
  10. semnum:1, semval:8  
  11. [redhat@localhost sem]$ ./seminfo 131075  
  12. key:585c7c37  
  13. semid:131075  
  14. nsems:2  
  15. -------sem details---------  
  16. semnum:0, semval:18  
  17. semnum:1, semval:8  
  18. [redhat@localhost sem]$ ./seminfo 131075  
  19. key:585c7c37  
  20. semid:131075  
  21. nsems:2  
  22. -------sem details---------  
  23. semnum:0, semval:18  
  24. semnum:1, semval:10  
  25. [1]+  Done                    ./semop 131075 1 -2 1 15  



iii.不设置SEM_UNDO,将第一个信号量减2;进程未退出时,信号量由18变成16;进程非正常退出时,保持16不变。
设置SEM_UNDO,将第二个信号量减2;进程未退出时,信号量由10变成8;进程非正常退出时,将2归还给信号量,信号量重新变回10

[plain]  view plain  copy
  1. [redhat@localhost sem]$ ./semop 131075 0 -2 0 10 & ./semop 131075 1 -2 1 15&  
  2. [1] 3352  
  3. [2] 3353  
  4. [redhat@localhost sem]$ ./seminfo 131075  
  5. key:585c7c37  
  6. semid:131075  
  7. nsems:2  
  8. -------sem details---------  
  9. semnum:0, semval:16  
  10. semnum:1, semval:8  
  11. [redhat@localhost sem]$ kill -9 3073  
  12. [redhat@localhost sem]$ kill -9 3074  
  13. [redhat@localhost sem]$ ./seminfo 131075  
  14. key:585c7c37  
  15. semid:131075  
  16. nsems:2  
  17. -------sem details---------  
  18. semnum:0, semval:16  
  19. semnum:1, semval:10  
  20. [2]+  已杀死               ./semop 131075 1 -2 1 15  



 

 

附:
seminfo与semop代码如下:
查看信号量信息:seminfo.c

[cpp]  view plain  copy
  1. 1 #include <stdio.h>  
  2.  2 #include <sys/sem.h>  
  3.  3 #include <stdlib.h>  
  4.  4 #include <errno.h>  
  5.  5   
  6.  6 #define SEMMSL 250  
  7.  7 #define BUFSIZE 50  
  8.  8   
  9.  9 #define error() \  
  10. 10 do {    \  
  11. 11         char buf[BUFSIZE];      \  
  12. 12         snprintf(buf, BUFSIZE, "[%s][%d][%d]\n", __FILE__, __LINE__, errno);    \  
  13. 13         perror(buf);    \  
  14. 14 } while(0);  
  15. 15   
  16. 16 void help(char *prgm)  
  17. 17 {  
  18. 18         printf("command : %s semid\n", prgm);  
  19. 19 }  
  20. 20   
  21. 21 int seminfo(int semid)  
  22. 22 {  
  23. 23         struct semid_ds semds;  
  24. 24         short semval[SEMMSL];  
  25. 25         int err;  
  26. 26   
  27. 27         err = semctl(semid, 0, IPC_STAT, &semds);  
  28. 28         if (err == -1) {  
  29. 29                 error();  
  30. 30                 return err;  
  31. 31         }  
  32. 32   
  33. 33         printf("key:%x\n", semds.sem_perm.__key);  
  34. 34         printf("semid:%d\n", semid);  
  35. 35         printf("nsems:%d\n", semds.sem_nsems);  
  36. 36   
  37. 37         if (semds.sem_nsems > SEMMSL) {  
  38. 38                 printf("SEMMSL small!!\n");  
  39. 39                 return -1;  
  40. 40         }  
  41. 41   
  42. 42         err = semctl(semid, 0 ,GETALL, semval);  
  43. 43         if (err == -1) {  
  44. 44                 error();  
  45. 45                 return err;  
  46. 46         }  
  47. 47   
  48. 48         printf("-------sem details---------\n");  
  49. 49         int i=0;  
  50. 50         for(; i < semds.sem_nsems; i++) {  
  51. 51                 printf("semnum:%d, semval:%d\n", i, semval[i]);  
  52. 52         }  
  53. 53   
  54. 54         return 0;  
  55. 55 }  
  56. 56   
  57. 57 int main(int argc, char *argv[])  
  58. 58 {  
  59. 59         int semid;  
  60. 60         int err;  
  61. 61   
  62. 62         if (argc != 2) {  
  63. 63                 help(argv[0]);  
  64. 64                 return -1;  
  65. 65           
  66. 66         semid = atoi(argv[1]);  
  67. 67           
  68. 68         err = seminfo(semid);  
  69. 69         if (err) {  
  70. 70                 exit(-1);  
  71. 71         }         
  72. 72           
  73. 73         return 0;  
  74. 74                   
  75. 75 }  

信号量操作:semop.c

[cpp]  view plain  copy
  1.  1 #include <stdio.h>  
  2.  2 #include <sys/sem.h>  
  3.  3 #include <stdlib.h>  
  4.  4 #include <errno.h>  
  5.  5 #include <unistd.h>  
  6.  6   
  7.  7 #define SEMMSL 250  
  8.  8 #define BUFSIZE 50  
  9.  9   
  10. 10 #define error() \  
  11. 11 do {    \  
  12. 12         char buf[BUFSIZE];      \  
  13. 13         snprintf(buf, BUFSIZE, "[%s][%d][%d]\n", __FILE__, __LINE__, errno);    \  
  14. 14         perror(buf);    \  
  15. 15 } while(0);  
  16. 16   
  17. 17 void help(char *prgm)  
  18. 18 {  
  19. 19         printf("command : %s semid semnum semops undo[0|1] sleeps[0-15]\n", prgm);  
  20. 20 }  
  21. 21   
  22. 22 int main(int argc, char *argv[])  
  23. 23 {  
  24. 24         int semid, semnum, semops, undo, sleeps;  
  25. 25         int err;  
  26. 26         struct sembuf sembuf;  
  27. 27   
  28. 28         if (argc != 6) {  
  29. 29                 help(argv[0]);  
  30. 30                 return -1;  
  31. 31         }  
  32. 32   
  33. 31         }  
  34. 32   
  35. 33         semid = atoi(argv[1]);  
  36. 34         semnum = atoi(argv[2]);  
  37. 35         semops = atoi(argv[3]);  
  38. 36         undo = atoi(argv[4]);  
  39. 37         sleeps = atoi(argv[5]);  
  40. 38   
  41. 39         if (undo != 0 && undo != 1) {  
  42. 40                 printf("invalid undo\n");  
  43. 41                 return -1;  
  44. 42         }  
  45. 43   
  46. 44         if (sleeps < 0 || sleeps > 15) {  
  47. 45                 printf("invalid sleeps\n");  
  48. 46                 return -1;  
  49. 47         }  
  50. 48   
  51. 49         sembuf.sem_num = semnum;  
  52. 50         sembuf.sem_op = semops;  
  53. 51         sembuf.sem_flg = undo ? SEM_UNDO : 0;  
  54. 52         err = semop(semid, &sembuf, 1);  
  55. 53         if (err) {  
  56. 54                 error();  
  57. 55                 return -1;  
  58. 56         }  
  59. 57   
  60. 58         sleep(sleeps);  
  61. 59   
  62. 60         return 0;  
  63. 61   
  64. 62 }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值