IPC信号量 sem

来源:互联网 发布:cdn用什么软件linux 编辑:程序博客网 时间:2024/06/05 07:58


(1)查看所有信号
ipcs -s
------ Semaphore Arrays --------
key        semid      owner      perms      nsems     
0x00008708 0          root      666        1         
0x000086f8 217120769  root      666        1         
0x0000870a 65538      root      666        1         
0x00008707 98307      root      666        1         
0x00008709 131076     root      666        1         
0x00008706 163845     root      666        1         
0x0000870b 196614     root      666        1  




(2)查看指定信号信息 -i
# ipcs -s -i 249823287


Semaphore Array semid=249823287
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Not set                   
ctime = Thu Aug 15 14:25:08 2013  
semnum     value      ncount     zcount     pid       
0          0          1          0          0         

# sysctl -a|grep sem
kernel.sem = 250        1024000 32      4096


查看当前信号量系统限制
# ipcs -ls
------ Semaphore Limits --------
max number of arrays = 4096     <------ 系统允许的 【信号集数组】 最大个数
max semaphores per array = 250    <------ 允许每个信号集数组管理多少个信号量, 信号数组包含多个信号
max semaphores system wide = 1024000    <----- 系统创建【信号量】最大数, 该值等于 (max number of arrays) * (max semaphores per array)
max ops per semop call = 32   <------- 每次semop操作的时候设置sem_op最大值
semaphore max value = 32767   <------- 信号量最大值


可以通过下面命令临时修改:
echo "5010 641280 5010 128" > /proc/sys/kernel/sem



(3)测试

测试1  (没有设置SEM_UNDO)

测试程序如下: 
int main(int argc, char * argv[])
{
int nRet = 0; 
int sem_id = 0;
Semaphore sem;
nRet = sem.create(0x112233, sem_id);
if(nRet)
{
  nRet = sem.open(0x112233, sem_id);
}
sem.acquire();  //sops[0].sem_flg = 0,没有指定 SEM_UNDO


while(true)
{
   sleep(5);
}

return nRet;
}


程序执行完信号量代码后查看信号量信息, value=0, 正常
root@PLATDEV:~# ipcs -s -i 249921584


Semaphore Array semid=249921584
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Thu Aug 15 14:50:26 2013  
ctime = Thu Aug 15 14:40:18 2013  
semnum     value      ncount     zcount     pid       
0          0          0          0          858       




kill 这个测试程序,再查看信号量信息, value依然等于0, 信号量没资源可用了!下次启动程序就被挂死!
root@PLATDEV:~# ipcs -s -i 249921584


Semaphore Array semid=249921584
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Thu Aug 15 14:50:26 2013  
ctime = Thu Aug 15 14:40:18 2013  
semnum     value      ncount     zcount     pid       
0                  0         1             0          858




我们重新启动进程在获取信号的时候, 由于信号没有资源进程挂死了。




测试2 (信号acquire不设置SEM_UNDO, release设置SEM_UNDO)


测试程序如下: 
int main(int argc, char * argv[])
{
int nRet = 0; 
int sem_id = 0;
Semaphore sem;
nRet = sem.create(0x112233, sem_id);
if(nRet)
{
  nRet = sem.open(0x112233, sem_id);
}
sem.acquire();  //sops[0].sem_flg = 0
sem.release();  //sops[0].sem_flg = SEM_UNDO   <---- 释放的时候设置 SEM_UNDO



while(true)
{
   sleep(5);
}

return nRet;
}


程序执行完信号量代码后查看信号量信息, value=1, 正常
# ipcs -s -i 275021825


Semaphore Array semid=275021825
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Wed Sep  4 17:19:48 2013  
ctime = Wed Sep  4 17:19:48 2013  
semnum     value      ncount     zcount     pid       
0                     1             0             0          31186


kill 这个测试程序,再查看信号量信息, value=0, 信号量没资源可用了!下次启动程序就被挂死!


# ipcs -s -i 275021825


Semaphore Array semid=275021825
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Wed Sep  4 17:26:20 2013  
ctime = Wed Sep  4 17:19:48 2013  
semnum     value      ncount     zcount     pid       
0                      0           0                  0          31186




测试3 (信号acquire设置SEM_UNDO, release不设置SEM_UNDO)


测试程序如下: 
int main(int argc, char * argv[])
{
int nRet = 0; 
int sem_id = 0;
Semaphore sem;
nRet = sem.create(0x112233, sem_id);
if(nRet)
{
  nRet = sem.open(0x112233, sem_id);
}
sem.acquire();  //sops[0].sem_flg = SEM_UNDO
sem.release();  //sops[0].sem_flg = 0



while(true)
{
   sleep(5);
}

return nRet;
}




程序执行完信号量代码后查看信号量信息, value=1, 正常
# ipcs -s -i  275185665
Semaphore Array semid=275185665
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Thu Sep  5 09:08:10 2013  
ctime = Thu Sep  5 09:08:10 2013  
semnum     value      ncount     zcount     pid       
0                 1          0          0          28548




kill 这个测试程序,再查看信号量信息, value=2, 信号量已经不正常了


# ipcs -s -i  275185665


Semaphore Array semid=275185665
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Thu Sep  5 09:08:46 2013  
ctime = Thu Sep  5 09:08:10 2013  
semnum     value      ncount     zcount     pid       
0               2          0             0          28548 






测试4 (信号acquire设置SEM_UNDO, release没设置SEM_UNDO)


测试程序如下: 
int main(int argc, char * argv[])
{
int nRet = 0; 
int sem_id = 0;
Semaphore sem;
nRet = sem.create(0x112233, sem_id);
if(nRet)
{
  nRet = sem.open(0x112233, sem_id);
}


for(int i=0; i<32768; i++)
{
  sem.acquire();  //sops[0].sem_flg = SEM_UNDO  
  sem.release();  //sops[0].sem_flg = 0
}


while(true)
{
   sleep(5);
}

return nRet;
}


执行到最后一次的时候会报错:(sem最大值32767)
semop(semid:280494082) acquire failed. errno:34, errmsg:Numerical result out of range
semop(semid:280494082) release success. 




程序执行完信号量代码后查看信号量信息, value=2, 已经不正常
# ipcs -s -i 280690690


Semaphore Array semid=280690690
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Thu Sep  5 15:57:10 2013  
ctime = Thu Sep  5 15:57:07 2013  
semnum     value      ncount     zcount     pid       
0          2          0          0          26913




kill 这个测试程序,再查看信号量信息
# ipcs -s -i 280690690


Semaphore Array semid=280690690
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Thu Sep  5 15:58:46 2013  
ctime = Thu Sep  5 15:57:07 2013  
semnum     value      ncount     zcount     pid       
0          32767      0          0          26913








测试5 (信号acquire设置SEM_UNDO, release设置SEM_UNDO)


测试程序如下: 
int main(int argc, char * argv[])
{
int nRet = 0; 
int sem_id = 0;
Semaphore sem;
nRet = sem.create(0x112233, sem_id);
if(nRet)
{
  nRet = sem.open(0x112233, sem_id);
}
sem.acquire();  //sops[0].sem_flg = SEM_UNDO  
sem.release();  //sops[0].sem_flg = SEM_UNDO


while(true)
{
   sleep(5);
}

return nRet;
}




程序执行完信号量代码后查看信号量信息, value=1, 正常
# ipcs -s -i 275218433


Semaphore Array semid=275218433
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Thu Sep  5 09:11:28 2013  
ctime = Thu Sep  5 09:11:28 2013  
semnum     value      ncount     zcount     pid       
0               1          0          0          28706 




kill 这个测试程序,再查看信号量信息, value=1,依然正常
# ipcs -s -i 275218433

Semaphore Array semid=275218433
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Thu Sep  5 09:13:53 2013  
ctime = Thu Sep  5 09:11:28 2013  
semnum     value      ncount     zcount     pid       
0                        1          0               0          28706 


测试6 (信号acquire设置SEM_UNDO, release设置SEM_UNDO, 在两者之间程序退出)

测试程序如下: 
int main(int argc, char * argv[])
{
int nRet = 0; 
int sem_id = 0;
Semaphore sem;
nRet = sem.create(0x112233, sem_id);
if(nRet)
{
  nRet = sem.open(0x112233, sem_id);
}
sem.acquire();  //sops[0].sem_flg = SEM_UNDO  
exit(-1);      
//程序退出, 这个测试类似测试3, 但系统处理机制不同
sem.release();  //sops[0].sem_flg = SEM_UNDO


while(true)
{
   sleep(5);
}

return nRet;
}




查看信号量信息, value=1,依然正常, 不同于测试3


# ipcs -s -i 275251201


Semaphore Array semid=275251201
uid=0    gid=0   cuid=0  cgid=0
mode=0666, access_perms=0666
nsems = 1
otime = Thu Sep  5 09:27:50 2013  
ctime = Thu Sep  5 09:27:50 2013  
semnum     value      ncount     zcount     pid       
0          1          0          0          29914


【总结】:
(1)SEM_UNDO 在进程异常退出信号没有释放资源场景很重要!
(2)SEM_UNDO 一定要成对使用



0 0