记录一次linux信号量sem_t使用bug
linux提供了互斥量pthread_mutex_t(pthread库) 用于线程间同步,进程间同步提供了信号量sem_t。如果把pthread_mutex_t放到共享内存中,并将其属性设置为PTHREAD_PROCESS_SHARED,则也能实现进程间的同步,相对而言比较麻烦。一般直接使用信号量更加方便。
这里讨论使用具名信号量以便在无血缘关系的进程之间做同步,主要涉及下面5个函数:
sem_open();//打开或者创建信号量
sem_wait();//获取信号量
sem_post();//挂出信号量
sem_close();//关闭信号量
sem_unlink();//销毁信号量
其中sem_unlink()的行为比较让人迷惑,linux内核文档描述为:
DESCRIPTIONsem_unlink() removes the named semaphore referred to by name. The semaphore name is removed immediately. Thesemaphore is destroyed once all other processes that have the semaphore open close it.
意思是执行该函数,会立即移除信号量的id名,并尝试销毁对应的信号量实体,只有所有打开了该信号量的进程都执行了sem_close(),执行sem_unlink()时才会真正销毁这个信号量。问题就出现了,id名与信号量实体可能出现分离,因为当某个进程A关闭了信号量(也就是执行了sem_close)并尝试执行sem_unlink的时候,并不能确保其他进程关闭了信号量,结果是信号量实体无法被真正销毁,它依然在内核中存在,且其他使用该信号量实体的进程依然可以工作正常。问题是,当进程A再次打开这个信号量时(使用sem_open(),id名不变),已经无法通过id名找到之前那个信号量实体了,打开的是一个全新的信号量,虽然id名与之前一样,内容却已经没有关联了。
这样一来,进程A就无法与其他进程同步了。只有其他进程也执行一次sem_close,并重新打开这个id名(sem_open()),才能重新连接到进程A打开的那个信号量实体,继续同步。因此“The semaphore name is removed immediately”,应该理解为"立即解除name 与信号量实体的绑定关系",且解除之后无法重新绑定。
在使用共享内存的过程中,shmctl(id,IPC_RMID,NULL)移除共享内存,好像也有类似的问题,没有实测过。
总结:
通常当一个进程退出时,需要关闭已经打开的信号量(sem_close),如果信号量属于这个进程(在这个进程里面create),还应该执行sem_unlink;如果信号量的归属权不是该进程,则只应该执行关闭。
现实使用的时候,进程可能异常挂掉退出,没有执行到sem_close这一步,甚至还没有来得及挂出信号量(sem_post)程序就挂了,问题比较复杂,不仅可能存在数据安全,还很有可能造成死锁。所以最好是当某个进程重启了,其他相关进程也重启一下,确保所有进程打开的是同一个信号量实体,可以一定程度避免信号量和共享内存连接异常的问题。
当然,最好是不要让程序有异常挂掉的情况,应该做好异常捕获和处理,减少程序未定义行为。
记录一次linux信号量sem_t使用bug相关推荐
- Linux信号量 sem_t简介
简介请移步: https://blog.csdn.net/qq_19923217/article/details/82902442 https://blog.csdn.net/evsqiezi/art ...
- 最全面的 linux 信号量解析
一.什么是信号量 信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有. 信号量的值为正的时候,说明它空闲.所测试的线程可以锁定而使用它.若为 0,说明它被占用,测试的线程 ...
- 记录第一次使用linux部署springbootweb项目
记录第一次使用linux部署springbootweb项目 收获感受 经过一下午的安装虚拟机.Linux系统.JDK1.8,项目打包,解决bug,终于项目部署成功!哈哈哈哈哈哈哈哈哈 收获还是不错的, ...
- Linux·信号量全解
目录 信号量 进程间 [无名信号量完成 有血缘关系的进程间 互斥] 知识点2[有名信号量 没有血缘进程互斥] 1.创建一个有名信号量 2.信号量的关闭: 3.信号量文件的删除 4.P操作 sem_wa ...
- linux申请信号量,linux 信号量
https://www.jianshu.com/p/6e72ff770244 无名信号量 只适合用于一个进程的不同线程 #include #include #include #include #inc ...
- linux terminal教程,Linux入门教程 - 如何记录和重放Linux终端会话
原标题:Linux入门教程 - 如何记录和重放Linux终端会话 来自:https://www.linuxmi.com/replay-linux.html 使用命令,我们可以在type文件中记录终端会 ...
- Linux系统下搭建BUG管理系统---禅道
Linux系统下搭建BUG管理系统---禅道 事前准备: Linux系统服务器,centos6.5版本 Windows系统本地电脑 禅道压缩包 Xshell4.xftp管理工具 1.安装mysql y ...
- 编译linux源码报错,记录一次Linux内核源码编译实验
记录一次Linux内核源码编译实验 文章目录 记录一次Linux内核源码编译实验 0. 实验环境 1. 选择.下载内核源码 2. 安装必要的依赖软件以及性能要求 3. 解压.配置和编译内核源码 3.1 ...
- 简洁介绍信号量sem_t的起因、原理与使用
简洁介绍信号量sem_t的起因.原理与使用 起因: 在对应用程序优化加速时,会使用多线程技术来进行加速.使用软件多线程可以让用户与底层硬件进行隔离.即不管实际底层硬件是否有多个执行单元,都可以使用多线 ...
- 如何向Linux内核提交代码,华人教授向 Linux 内核提交含 Bug 代码,Linux 管理员直接拉黑整所大学!...
技术编辑:小魔丨发自 思否编辑部公众号:SegmentFault Linux 内核是目前最大的软件项目之一,拥有 2800 万行代码.世界各地的贡献者每天向 Linux 内核管理员提交大量 patch ...
最新文章
- 6位有符号补码阵列乘法器_C/C++学习日记:原码、反码和补码
- 微软职位内部推荐-Software Engineer II-Data Mini
- 域名无法加入域解决方法
- 把数据保存到cook_JavaScript数据存储 Cookie篇
- ApkTool反编译出错brut.common.brutexception及java.io.filenotfoundexception 之一
- SpringMVC流程图示
- Java中的查找树和哈希表(一级)
- Pythont特殊语法filter,map,reduce,apply
- Linux环境_源码安装LibreOffice实现文件在线预览doc,doxc,xls,xlsx,ppt,pptx 文件
- 自动化数据增强:实践、理论和新方向
- linux能秒创虚拟机吗,linux下5秒创建rhel7虚拟机
- SP913 QTREE2 - Query on a tree II
- Window环境下使用C#调用VBScript、JavaScript等脚本
- 重复抽样与非重复抽样
- IOS 保存图片至相册
- 没有 4K 和新处理器,任天堂的新 Switch 为什么还能吸引圈外玩家买单?
- PlayReady 和WideVine
- 【STM32F407开发板用户手册】第2章 STM32F407的开发环境搭建
- c语言程序设计网课作业答案,知到C语言程序设计基础网课答案
- Modern C++ JSON nlohmann::json 使用详解