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. python高级编程:有用的设计模式1

    # -*- coding: utf-8 -*-__author__ = 'Administrator'#python高级编程:有用的设计模式#设计械是可复用的,某种程序上它对软件设计中觉问题提供的语言 ...

  2. 【转载自i春秋】图片马合成方法

    1.将图片和一句话木马放在同一个文件夹 2.创建快捷方式,将起始位置修改为图片和txt文本的路径. 3.进行合成,命令如下 copy .png /b + .txt /a .png 4.成功!自行测试. ...

  3. 最流行的android组件大全

    目录 [−] 工具和教程 UI组件 类库 游戏引擎 Android HTML5应用 Android 是目前最流行的移动操作系统(还需要加之一吗?). 随着新版本的不断发布, Android的功能也日益 ...

  4. alt和title的用法区别

    经常用到这两个属性,但是一直没有总结他们的区别.现在我对他们两个的用法做一下总结: 相同点:他们都会飘出一个小浮层,显示文本内容. 不同点: 1.alt只能是元素的属性,而title即可以是元素的属性 ...

  5. Javascript实现表格行排序

    网站开发中凡是用到表格来展示数据的,往往都要根据某个列来对行排序,下面是我从书上看到的一个行排序例子,看过后受益匪浅,故分享出来. 直接献上完整代码: <!doctype html> &l ...

  6. IP地址变动后,https://localhost:1158/em无法访问解决办法

    一.解决的方法:重新配置em 二.步骤: 1.在 dos命令下输入 emca –repos drop 注意:监听端口号是一般是1521,特殊情况要在配置文件中找 2.成功删除资料档案库后,在dos下再 ...

  7. 使用cocoapods后 三方库的头文件没有代码提示?

    选择Target -> Build Settings 菜单,找到\”User Header Search Paths\”设置项 新增一个值"${SRCROOT}",并且选择\ ...

  8. IOS — 关于Socket传输文件需要自定义延时或者包大小的情况

    1. 首先导入头文件 #include <stdio.h> #include <errno.h> #include <string.h> #include < ...

  9. SQL中将某个表中的多行数据在一个字段显示

    项目需求:将某个表中的多行数据在一个字段显示,如下: 比如表A中有字段 ID,NAME, 表B中有字段ID,PID,DES, 表A,表B中的数据分别如下: ID NAME1 张三2 李四 ID PID ...

  10. Oracle复杂查询

    1:列出所有员工的姓名,部门名称,和工资 select a1.ename,a1.sal,a2.dname from emp a1,dept a2 where a1.deptno = a2.deptno ...