sem_unlink在man手册里有这么一段话:

sem_unlink() removes the named semaphore referred to by name.  
The semaphore name is removed immediately. The semaphore is
destroyed once all other processes that have the semaphore open close it.

这段话的意思是说,sem_unlink会马上删除指定的信号量名,但要等到所有打开该信号量的进程关闭该信号量后才删除该信号。详细地说,当进程创建一个有名信号量,会在/dev/shm下生成一个sem.xxx的文件,所有打开该信号量的进程(包括创建它的进程)都会增加该文件的引用计数,并且这个计数由内核管理。当调用sem_unlink时,/dev/shm下的sem.xxx文件会马上被删除,但是信号量本身并没有被删除,所有已打开该信号量的进程仍能正常使用它。直到所有打开该信号量的进程关闭该信号量后,内核才真正删除信号量。

  因此,信号量跟sem.xxx并不是共存亡的。下面来测试下:

/* sem_create.cpp */
#include <iostream>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <semaphore.h>
#include <unistd.h>
#include <cerrno>
#include <cstring> int main()
{
sem_t *psem = sem_open( "/sem_test",O_CREAT,S_IRWXU, );
if ( SEM_FAILED == psem )
{
std::cout << "sem_open fail:" << strerror(errno) << std::endl;
return ;
} int sval = ;
sem_getvalue( psem,&sval ); std::cout << "sleep now ....value is " << sval << std::endl;
sleep( ); sem_getvalue( psem,&sval );
std::cout << "wake up ....value is " << sval << std::endl; sem_post( psem );
sem_getvalue( psem,&sval );
std::cout << "raise value and try again ....value is " << sval << std::endl; sem_close( psem );
}
/**
*
* sem_destruct.cpp
*/ #include <iostream>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <semaphore.h>
#include <cerrno>
#include <cstring> int main()
{
sem_t *psem = sem_open( "/sem_test",O_CREAT,S_IRWXU, );
if ( SEM_FAILED == psem )
{
std::cout << "sem_open fail:" << strerror(errno) << std::endl;
return ;
} std::cout << "decrease value and remove sem now..." << std::endl;
sem_wait ( psem ); sem_close( psem );
sem_unlink( "/sem_test" ); std::cout << "sem should remove from /dev/shm,but not really remove" << std::endl;
}

分别编译上面的文件:

g++ -pthread -o sem_create sem_create.cpp
g++ -pthread -o sem_destruct sem_destruct.cpp

先运行sem_create,再运行sem_destruct这时个可以看到输出为:

xzc@xzc-HP-ProBook-4446s:~/code/sem$ ./sem_create
sleep now ....value is
xzc@xzc-HP-ProBook-4446s:~/code/sem$ ./sem_destruct
decrease value and remove sem now...
sem should remove from /dev/shm,but not really remove
wake up ....value is
raise value and try again ....value is

可以看到,即使sem_destruct从/dev/shm把信号量删除了,ls /dev/shm也确认对应的文件删除了。但是经过sleep的sem_create进程在wake up后仍能对信号量进行操作。

  可以看到,有名信号量一旦打开后,跟名字并没有多大关系。下面再来测试有名信号量调用sem_unlink但仍有进程在使用,这时另外一个进程又要创建同名信号量的情况

/**
*
* sem_again.cpp
*/ #include <iostream>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <semaphore.h>
#include <unistd.h>
#include <cerrno>
#include <cstring> int main()
{
sem_t *psem = sem_open( "/sem_test",O_CREAT|O_EXCL,S_IRWXU, );
if ( SEM_FAILED == psem )
{
std::cout << "sem_open fail:" << strerror(errno) << std::endl;
return ;
} int sval = ;
sem_getvalue( psem,&sval ); //std::cout << "sleep now ....value is " << sval << std::endl;
//sleep( 30 ); sem_getvalue( psem,&sval );
std::cout << "value is " << sval << std::endl; sem_post( psem );
sem_getvalue( psem,&sval );
std::cout << "raise value and try again ....value is " << sval << std::endl; sem_close( psem );
sem_unlink( "/sem_test" );
}

编译一下:g++ -pthread -o sem_again sem_again.cpp,然后依次运行sem_create、sem_destruct、sem_again

xzc@xzc-HP-ProBook-4446s:~/code/sem$ ./sem_create
sleep now ....value is xzc@xzc-HP-ProBook-4446s:~/code/sem$ ./sem_destruct
decrease value and remove sem now...
sem should remove from /dev/shm,but not really remove xzc@xzc-HP-ProBook-4446s:~/code/sem$ ./sem_again
value is
raise value and try again ....value is wake up ....value is
raise value and try again ....value is

在sem_again中特意使用了O_CREATE|O_EXCL标志,如果已存在同名信号量,则创建失败。但从上面的结果来看,创建成功并且互不干扰。也就是说,一个有名信号量,在打开并调用sem_unlink后可以当作无名信号量来使用(但这时新的进程还想使用该信号量,不可能了)。

  注:上面只做了简单测试,并未测试sem_unlink后各进程的竞争情况,在生产环境请自行测试。

PS:在debian 6上,不用unistd.h也能调用sleep函数,在ubuntu 14.04上不行。在debian 6上是链接的库是-lrt,在ubuntu 14.04上是-pthread,-lrt不行。linux这是要闹哪样。

关于sem_unlink什么时候删除信号量的更多相关文章

  1. Linux 共享内存 详解

    一.什么是共享内存区 共享内存区是最快的可用IPC形式.它允许多个不相关的进程去访问同一部分逻辑内存.如果需要在两个运行中的进程之间传输数据,共享内存将是一种效率极高的解决方案.一旦这样的内存区映射到 ...

  2. 【转载】Linux的进程间通信-信号量

    原文:Linux的进程间通信-信号量 Linux的进程间通信-信号量 版权声明: 本文章内容在非商业使用前提下可无需授权任意转载.发布. 转载.发布请务必注明作者和其微博.微信公众号地址,以便读者询问 ...

  3. 进程间通信之POSIX信号量

    POSIX信号量接口,意在解决XSI信号量接口的几个不足之处: POSIX信号量接口相比于XSI信号量接口,允许更高性能的实现. POSIX信号量接口简单易用:没有信号量集,其中一些接口模仿了我们熟悉 ...

  4. Linux进程同步之POSIX信号量

    POSIX信号量是属于POSIX标准系统接口定义的实时扩展部分.在SUS(Single UNIX Specification)单一规范中,定义的XSI IPC中也同样定义了人们通常称为System V ...

  5. Linux多线程实践(5) --Posix信号量与互斥量解决生产者消费者问题

    Posix信号量 Posix 信号量 有名信号量 无名信号量 sem_open sem_init sem_close sem_destroy sem_unlink sem_wait sem_post ...

  6. POSIX信号量

    DESCRIPTION POSIX 信号量允许进程间和线程间同步他们的操作. 一个信号量是一个整型(integer),其值不能小于0. 信号量允许2中操作:给信号量的值加1(sem_post); 给信 ...

  7. linux c编程:Posix信号量

    POSIX信号量接口,意在解决XSI信号量接口的几个不足之处: POSIX信号量接口相比于XSI信号量接口,允许更高性能的实现. POSIX信号量接口简单易用:没有信号量集,其中一些接口模仿了我们熟悉 ...

  8. 进程同步与相互排斥:POSIX有名信号量

    在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量. 无名信号量一般用于线程间同步或相互排斥,而有名信号量一般用于进程间同步或相互排斥. 它们的差别和管道及命名管道的差别类似.无 ...

  9. C实现进程间通信(管道; 共享内存,信号量)

    最近学习了操作系统的并发:以下是关于进程间实现并发,通信的两个方法. 例子: 求100000个浮点数的和.要求: (1)随机生成100000个浮点数(父进程). (2)然后创建4个后代进程,分别求25 ...

随机推荐

  1. jQuery鼠标悬停图片放大显示

    jQuery鼠标悬浮放于图片上之后图片放大显示的效果,即鼠标移到图片上图片突出显示,鼠标移开后恢复原来的模样,你可以在图片滚动效果中加上本特效,相信会更炫一些. <!DOCTYPE html P ...

  2. tomcat 7配置数据库连接池,使用SQL Server2005实现

    昨 天看了一些网上的tomcat数据库连接池配置的东西,但是一直没配好,主要原因是网上的文章几乎没有针对tomcat 7进行配置的,而且针对SQL SERVER的也不多,今天上午看了官方的文档,花了一 ...

  3. LoadRunner录制回放脚本RecContentType=application/json报错

    今天做一个新项目,项目系统的框架是用SSH,特意查看了一下项目源码,用的ajax提交比较多,主要的问题是该系统对IE(8~10)浏览器都不兼容,无法进行录制. 是问题,总有解决的办法! 我本机为Loa ...

  4. fread(),fwrite() 读/写流

    C 库函数 - fread() 描述 C 库函数 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 从给定流 strea ...

  5. 将samba加入到windows域《转载》

    将samba加入到windows域 那什么是域呢? 一台Windows计算机,它要么隶属于工作组,要么隶属于域.所以说到域,我们就不得不提一下工作组,工作组是MS的概念,一般的普遍称谓是对等网. 工作 ...

  6. python - socket练习(输入系统命令)

    socket_server端代码: #!/usr/bin/env python # -*- coding:utf-8 -*- # Auther: pangguoping import socket i ...

  7. .NET程序猿 - 提升幸福感的组件一览

    1.Newtonsoft.Json.net 操作JSON最简便的方式.  .Net 3.5开始,Framework集成Json序列化器:JavaScriptSerializer,然而Json.net给 ...

  8. HashMap陷入死循环的例子

    //使用这个例子可以模拟HashMap陷入死循环的效果,可能需要执行多次才会出现. 1 package com.hanzi; import java.util.HashMap; public clas ...

  9. Silverlight 设置颜色

    透明色:00ff00ff //设置柱状图的颜色                ColorSet cs = new ColorSet();                cs.Id = "co ...

  10. GDB调试一

    http://blog.csdn.net/haoel/article/details/2881 GDB主要调试的是C/C++的程序.要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行 ...