当操作信号量(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