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

[redhat@localhost sem]$ ipcmk -S 2
Semaphore id: 131075
[redhat@localhost sem]$ ./seminfo
command : ./seminfo semid
[redhat@localhost sem]$ ./seminfo 131075
key:585c7c37
semid:131075
nsems:2
-------sem details---------
semnum:0, semval:0
semnum:1, semval:0
[redhat@localhost sem]$ ./semop
command : ./semop semid semnum semops undo[0|1] sleeps[0-15]
[redhat@localhost sem]$ ./semop 131075 0 20 0 0
[redhat@localhost sem]$ ./semop 131075 1 10 0 0
[redhat@localhost sem]$ ./seminfo 131075
key:585c7c37
semid:131075
nsems:2
-------sem details---------
semnum:0, semval:20
semnum:1, semval:10



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

[redhat@localhost sem]$ ./semop 131075 0 -2 0 0
[redhat@localhost sem]$ ./semop 131075 1 -2 1 15 &
[1] 3339
[redhat@localhost sem]$ ./seminfo 131075
key:585c7c37
semid:131075
nsems:2
-------sem details---------
semnum:0, semval:18
semnum:1, semval:8
[redhat@localhost sem]$ ./seminfo 131075
key:585c7c37
semid:131075
nsems:2
-------sem details---------
semnum:0, semval:18
semnum:1, semval:8
[redhat@localhost sem]$ ./seminfo 131075
key:585c7c37
semid:131075
nsems:2
-------sem details---------
semnum:0, semval:18
semnum:1, semval:10
[1]+  Done                    ./semop 131075 1 -2 1 15



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

[redhat@localhost sem]$ ./semop 131075 0 -2 0 10 & ./semop 131075 1 -2 1 15&
[1] 3352
[2] 3353
[redhat@localhost sem]$ ./seminfo 131075
key:585c7c37
semid:131075
nsems:2
-------sem details---------
semnum:0, semval:16
semnum:1, semval:8
[redhat@localhost sem]$ kill -9 3073
[redhat@localhost sem]$ kill -9 3074
[redhat@localhost sem]$ ./seminfo 131075
key:585c7c37
semid:131075
nsems:2
-------sem details---------
semnum:0, semval:16
semnum:1, semval:10
[2]+  已杀死               ./semop 131075 1 -2 1 15



 

 

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

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

信号量操作:semop.c

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


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值