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. Oracle insert update 时间处理

    24小时表示方法:to_date(’ ::’,’yyyy-mm-dd hh24:mi:ss’) 12小时表示方法:to_date(’ ::’,’yyyy-mm-dd hh:mi:ss’) ','S75 ...

  2. html5+css3中的background: -moz-linear-gradient 用法 (转载)

    转载至-->http://www.cnblogs.com/smile-ls/archive/2013/06/03/3115599.html 在CSS中background: -moz-linea ...

  3. NetAnalyzer笔记 之 六 用C#打造自己的网络连接进程查看器(为进程抓包做准备)

    [创建时间:2016-04-13 22:37:00] NetAnalyzer下载地址 起因 最近因为NetAnalyzer2016的发布,好多人都提出是否可以在NetAnalyzer中加入一个基于进程 ...

  4. js练习【DOM操作】

    完成效果: 演示地址:http://codepen.io/anon/pen/jPbYWq HTML: <!DOCTYPE html> <html lang="en" ...

  5. jquery Tabs选项卡切换

    效果: HTML部分: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...

  6. JSON解析---初识

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式 全然独立于语言的文本格式 易于人阅读和编写 易于解析和生成 (网络传输速度快) JSON语法规则 数据在 ...

  7. AIX下RAC搭建 Oracle10G(一)检測系统环境

    AIX下RAC搭建系列 环境 节点 节点1 节点2 小机型号 IBM P-series 630 IBM P-series 630 主机名 AIX203 AIX204 交换机 SAN光纤交换机 存储 S ...

  8. [RxJS] Toggle A Stream On And Off With RxJS

    This lesson covers how to toggle an observable on and off from another observable by showing how to ...

  9. java基础之反射

    反射的定义,反射的特性,反射的应用

  10. MVC学习四

    第七节   讲述了增加model中类的属性,由于数据库中已存在表,表中没有存在新加的列,所以可以删除数据库或者在数据库中新增一列,另可以在controller中新增一个数据库初始化的类,并在Globa ...