linux进程间通信:POSIX信号量
文章目录
- 概念描述
- 编程接口
- 注意事项
- 编程案例
- 信号量基本接口使用案例
- 信号量父子进程间通信
- 信号量实现 两进程之间通信
概念描述
- 英文:
semaphore
简称SEM,主要用来进行进程间同步 - 本质:内核维护的一个正整数,可对其进行各种+/-操作
- 分类:systemV 信号量、POSIX 有名信号量、POSIX 无名信号量
- 用途:用来标示系统中可用资源的的个数,协调各个进程有序的访问资源,防止发生冲突
- P操作:程序在进入临界区之前要对资源进行申请,对资源的引用计数要-1,当资源个数为0时进程p操作会发生阻塞
- V操作:程序离开临界区后要释放相应的资源,对资源对引用计数要+1
编程接口
以下接口编码过程中都可以通过man sem_open
这种方式查看接口对具体使用方式,详细信息则不列举
sem_t *sem_open(const char *name, int oflag); //使用字符串创建一个信号量
sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value); //使用字符串创一个一个信号量,并初始化信号量的值
int sem_close(sem_t *sem);
int sem_post(sem_t *sem); //信号量的v操作 +1
int sem_wait(sem_t *sem); //信号量的p操作 -1
int sem_trywait(sem_t *sem); //信号量进行p操作,但是值已经为0,此时会立即返回错而非阻塞//信号量进行p操作,如信号量的值为0,则阻塞abs_timeout结构体中的时间内还是无法执行p操作,则返回错误
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
int sem_unlink(const char *name);//删除名称为name的信号量
int sem_getvalue(sem_t *sem, int *sval);//获取信号量sem所代表的value数值
注意事项
- 以上编程接口包含头文件:
#include <semaphore.h>
- 编译时需指定:
-lpthread
进行编译
编程案例
linux系统中创建的信号量存放路径为/dev/shm
信号量基本接口使用案例
sem_demo.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>int main (){//创建信号量并初始化信号量的value值为4unsigned int sem_value = 4;sem_t *sem = sem_open("posix_sem", O_RDWR | O_CREAT,0777,sem_value);if (sem == SEM_FAILED) {printf("sem_open failed\n");_exit(-1);}//获取信号量的value值if (sem_getvalue(sem,&sem_value) != -1) {printf("sem_getvalue is %d\n",sem_value);}//对信号量进行p(-1)操作sem_wait(sem);sem_wait(sem);sem_wait(sem);sem_wait(sem);//sem_trywait(sem);//并不会发生阻塞,此时sem值已经为0,无法再进行p操作if(sem_getvalue(sem,&sem_value) != -1) {printf("sem_getvalue after sem_wait is %d\n",sem_value);}//对信号量进行v(+1)操作sem_post(sem);sem_post(sem);sem_post(sem);sem_post(sem);if(sem_getvalue(sem,&sem_value) != -1) {printf("sem_getvalue after sem_post is %d\n",sem_value);}if(sem_close(sem) != -1) {printf("sem_close success\n");}printf("wait for unlink sem\n");sleep(10);//删除名称为posix_sem信号量if(sem_unlink("posix_sem") != -1) {printf("sem_unlink success \n");}return 0;
}
编译gcc sem_demo.c -lpthread
输出如下:
sem_getvalue is 4
sem_getvalue after sem_wait is 0
sem_getvalue after sem_post is 4
sem_close success
wait for unlink sem
sem_unlink success
同时在等待10秒删除期间我们查看/dev/shm
目录下的sem文件存在,当10秒过后sem文件则被删除
信号量父子进程间通信
sem_comu.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>#define SEM_NAME "posix_sem_comu"int main (){int i = 0, j = 0,sem_val = 0,ret;sem_t *sem;sem = sem_open(SEM_NAME, O_CREAT,0666,1);ret = fork();if (ret == -1) {printf("sem_open failed \n");sem_close(sem);sem_unlink(SEM_NAME);_exit(-1);}//创建的子进程,执行10次p操作,每次间隔1秒else if(ret == 0) {while (i++ <= 10) {sem_wait(sem);if (sem_getvalue(sem,&sem_val) != -1) {printf("child process :sem value is %d\n",sem_val);sleep(1);}}_exit(1);}//父进程执行10次v操作,每次间隔两秒else {while (j++ <=10) {sem_post(sem);if (sem_getvalue(sem,&sem_val) != -1) {printf("prarent process :sem value is %d\n",sem_val);sleep(2);}}}//最终删除sem信号量sem_close(sem);if (sem_unlink(SEM_NAME) != -1) {printf("sem_unlink success \n");}return 0;
}
编译:gcc sem_comu.c -o comu -lpthread
输出如下,可以很明显的看到子即使子进程的p操作频率快于父进程v操作,但是对同一信号量,他们仍然能够有序同步访问。因为子进程p操作频率较快,此时信号量的value会很快减为0,子进程此时再进行p操作会发生阻塞;直到父进程执行v操作将信号量的值变为1子进程才能继续访问
prarent process :sem value is 2
child process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
child process :sem value is 0
prarent process :sem value is 1
sem_unlink success
信号量实现 两进程之间通信
两个进程,使用同一个信号量共同访问一个临界区,利用信号量的pv操作,实现同步访问
sem_post.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>int main(){char *name = "/posix_sem";int j = 0, sem_value = 4;sem_t *sem;sem = sem_open(name, O_CREAT, 0666, sem_value);if (sem == SEM_FAILED) {printf("sem open failed \n");_exit(-1);}printf("sem_open %s success \n",name);//对信号量进行5次 v操作,每次间隔5秒while(j++ <= 10) {if(sem_post(sem) == -1) {printf("sem _posd failed\n");_exit(-1);}if(sem_getvalue(sem,&sem_value) != -1) {printf("sem post success %d\n",sem_value);}sleep(5);}sleep(10);if(sem_close(sem) != -1) {printf("sem_close success \n");}if (sem_unlink(name) != -1) {printf("sem_unlink success \n");}return 0;
}
sem_wait.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#include <fcntl.h>int main(){char *name = "/posix_sem";int j = 0, sem_value = 4;sem_t *sem;sem = sem_open(name, O_CREAT, 0666, sem_value);if (sem == SEM_FAILED) {printf("sem open failed \n");_exit(-1);}printf("sem_open %s success \n",name);//对信号量进行p操作,每次间隔5秒,总共进行10次while(j++ <= 10) {if(sem_post(sem) == -1) {printf("sem _posd failed\n");_exit(-1);}if(sem_getvalue(sem,&sem_value) != -1) {printf("sem post success %d\n",sem_value);}sleep(5);}//执行结束后关闭信号量,并删除信名称为name的信号量sleep(10);if(sem_close(sem) != -1) {printf("sem_close success \n");}if (sem_unlink(name) != -1) {printf("sem_unlink success \n");}return 0;
}
编译:
gcc sem_post.c -o post -lpthread
gcc sem_wait.c -o wait -lpthread
可以看到输出如下,两进程是能够正常进行信号量value值的访问同步
相关文章:
指针小白:修改*p与p会对相应的地址的变量产生什么影响?各个变量指针的长度为多少?...
这两天敲代码碰到了一个这样的问题 代码如下: 1 #include <stdio.h>2 #include <stdlib.h>3 int main()4 {5 int num1 10;6 7 int* p&num1;8 *p 20;9 10 printf("%p\n", &num1); 11 printf("%d\…
MVC自带表单效验
废话不说,直接上代码,一看就明白 源地址:http://www.cnblogs.com/sixiangqimeng/p/3561313.html [StringLength(5,ErrorMessage "*长度小于5")][Required(ErrorMessage "*必填啊!")][Required(ErrorMessage…
mysql求每个订单的平均价_MySQL – 选择所有客户和每个客户的总订单和总价值
SELECT a.ID,a.Name,COUNT(b.Customer) totalOrders,SUM(b.value) total_valueFROM Customers aLEFT JOIN Orders bON a.ID b.CustomerGROUP BY a.ID,a.Name要么SELECT a.ID,a.Name,COUNT(b.Customer) totalOrders,COALESCE(SUM(b.value), 0) total_valueFROM Customers aLEFT…
windows server 2008设置远程桌面连接最大数量
windows server 2008设置远程桌面连接最大数量 系统默认远程桌面连接的数量为1 打开控制面板---管理工具---远程桌面服务---远程桌面会话主机设置---把"限制每个用户只能进行一个会话"勾选去掉; 然后双击连接中的RDP-Tcp---网络适配器--最大连接数 修改为…
BZOJ1002 [FJOI2007]轮状病毒(最小生成树计数)
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 7125 Solved: 3878[Submit][Status][Discuss]Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的…
linux进程间通信:POSIX 共享内存
文章目录思维导图通信原理优势POSIX 共享内存 编程接口编程案例思维导图 之前学习过sysemV 的共享内存的实现及使用原理,参考linux进程间通信:system V 共享内存 POSIX 同样提供共享内存的接口,基本原理和system V的共享内存是一样的。 通信…
求二进制中1的个数(编程之美2.1)
行文脉络 解法一——除法解法二——移位解法三——高效移位解法四——查表扩展问题——异或后转化为该问题对于一个字节(8bit)的变量,求其二进制“1”的个数。例如6(二进制0000 0110)“1”的个数为2,要求算…
mysql管理用户数据库_MySQL 数据库管理(一)(用户与受权)
前言在企业信息化的过程当中,数据库中库和表都会大量存在,须要分配给管理者核实的权限进行操做合理地分配权限,可使数据库管理井井有理,各个管理者只须要关注本身负责的内容,也可避免误操做对系统形成损失1、用户与受权…
Smart-linkmonitor-link配置注意事项
一、应用场合 Smart Link用于双上行组网,Monitor Link一般用于与Smart Link的联动,配置在Smart Link的上游设备。 二、注意事项 在配置过程中,请注意以下几点: ? 1、指定实例之前请先配置MSTP实例。MSTP的实例和VLAN映射关系发生…
封装OpenCL类
以上一篇《OpenCL入门测试》为基础,将函数封装到类中,方便调用。 #include <cstdlib> #include <iostream> #include <iomanip> #include <cstring> #include <cassert> #include <windows.h> #define CL_USE_DEPRE…
linux系统调用 ftruncate设置文件大小
系统调用ftruncate可以将一个文件裁剪为指定的大小,函数描述如下: 头文件:<unistd.h> <sys/types.h>函数使用: int truncate(const char *path, off_t length); int ftruncate(int fd, off_t length);函数参数&…
剑指 offer set 22 数组中的逆序数
总结 1. 题目为归并排序的变形, 不过我完全没想到 2. 在归并排序进行字符组 merge 时, 统计逆序数. merge 后, 两个子数组是有序的了, 下次再 merge 的时候就能以 o(n) 的时间内找到某一个逆序对第二个元素的个数 转载于:https://www.cnblogs.com/xinsheng/p/3564026.html
qt信号发送间隔短而槽耗时多_Qt信号槽问题汇总 - osc_9q1dp3jk的个人空间 - OSCHINA - 中文开源技术交流社区...
1. 发送一次信号,调用多次槽函数问题在同一个类中,多次链接QObject::connect(sender, SIGNAL(signalSender(QString, int)), receiver, SLOT(onSignalSender(QString, int))); 会导致发送一次信号signalSender(QString, int) 多次调用槽函数(onSignalSen…
一劳永逸关闭Windwos默认共享
对于IPC$,找到注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA下的RestrictAnonymous项,并将键值改为1。 对于其它默认共享,在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters下&#…
springboot 集成mybatis时日志输出
application.properties(yml)中配置的两种方式: 这两种方式的效果是一样的,但是下面一种可以指定某个包下的SQL打印出来,上面这个会全部的都会打印出来。 转载于:https://www.cnblogs.com/z0909y/p/10077565.html
linux文件IO与内存映射:用户空间的IO缓冲区
文章目录用户空间IO缓冲区产生IO缓冲区 描述IO缓冲区的写模式自定义IO缓冲区用户空间IO缓冲区产生 系统调用过程中会产生的开销如下: 切换CPU到内核态进行数据内容的拷贝,从用户态到内核态或者从内核态到用户态切换CPU到用户态 以上为普通到系统调用过…
java zookeeper_Java zookeeper开发实例
1、安装zookeeper下载zk http://archive.cloudera.com/cdh5/cdh/5/配置文件tickTime2000initLimit10syncLimit5# zk数据保存目录dataDir/usr/local/zookeeper/dataclientPort2181启动:bin/zkServer.sh start客户端命令行链接:bin/zkCli.sh2、拷贝zookeep…
【转】Maven Jetty 插件的问题(css/js等目录死锁)的解决
Maven Jetty 插件的问题(css/js等目录死锁,不能自动刷新)的解决:1. 打开下面的目录:C:\Users\用户名\.m2\repository\org\eclipse\jetty\jetty-webapp\,在进入版本对应的子目录,例如8.1.3.v2012…
ORA-4031错误深入解析
报ORA-4031错误时,我们通常可以根据Oracle无法分配多少字节的内存,来判断共享池碎片的严重程度,以下是4031错误官方的解释:[oracleguoyj ~]$ oerr ORA 403104031, 00000, "unable to allocate %s bytes of shared memory (\&…
buffers与cached的区别
具体参考以下博文: 1、https://www.cnblogs.com/chenpingzhao/p/5161844.html 2、https://blog.csdn.net/heweimingming/article/details/52230293 3、http://www.cnblogs.com/zhoug2020/p/6336453.html 其中3有top命令的详解。转载于:https://www.cnblogs.com/jia…
linux文件IO与内存映射:分散/聚集IO技术(scatter-gather)
前言 根据上文我们学习到的用户空间的IO缓冲区,操作系统为了减少系统调用的次数,节省系统开销,提出了用户空间的IO缓冲区,即为用户空间的文件读写开辟一段可以利用setvbuf配置大小的内存空间来作为文件IO缓冲区。 描述 为了在以…
android jni 调用 java_Android与JNI(二) ---- Java调用C++ 动态调用
目录:1. 简介2. JNI 组件的入口函数3. 使用 registerNativeMethods 方法4. 测试5. JNI 帮助方法6. 参考资料1. 简介Android与JNI(一)已经简单介绍了如何在 android 环境下使用 JNI 了。但是遵循 JNI 开发的基本步骤似乎有点死板,而且得到的本地函数名太…
如何查找并干掉僵尸进程
查找命令:ps -A -o stat,pid,ppid,cmd | grep -e ^[Zz] 找到之后 kill掉,然后用top命令查看是否kill成功,如果失败,kill 父进程。 转载于:https://www.cnblogs.com/kfx2007/p/3572249.html
[转] WINCC教学视频
原文地址http://www.ad.siemens.com.cn/club/bbs/post.aspx?b_id5&a_id1049763&s_id17&num0#anch WinCC 变量归档系列视频: http://www.ad.siemens.com.cn/service/elearning/cn/SerialVideo.aspx?vsid136 WinCC亚洲版高级工程师培训视频:…
UNL(Ubiquitous Navigation Lab)
转载于:https://www.cnblogs.com/Forwithy/p/10080078.html
linux 文件IO与内存映射:内存映射
前言 前面几篇我们学习了用户空间的IO缓冲区,以及IO缓冲区的分散聚合IO技术. 为了减少系统调用的次数,提升系统性能,操作系统开发者门提出了这么多的缓存技术。 但是到这里这些技术同样有不足的地方:不论是读或者写文件,都需要将…
Java网页数据采集器[下篇-数据查询]【转载】
本期概述 上一期我们学习了如何将html采集到的数据存储到MySql数据库中,这期我们来学习下如何在存储的数据中查询我们实际想看到的数据. 数据采集页面 2011-2012赛季英超球队战绩 如果是初学者 以下可能对你有帮助 Java如何操作MySql?在使用java 操作MySql数据库之前 我们需要…
loadrunner 调用java_LoadRunner调用Java程序—性能测试
为了充分利用LoadRunner的场景控制和分析器,帮助我们更好地控制脚本加载过程,从而展现更直观有效的场景分析图表。本次将重点讨论LoadRunner如何调用Java测试代码,完成压力测试。通常我们在执行一些Server的压力测试的时候,总会不…
《The Art of Readable Code》 读书笔记 01
放假前在学校图书馆借了一本新书《The Art of Readable Code》,寒假回来看看,写写其中的Key Idea 、summary和一些读书笔记。 Preface 前言部分主要概况讲了本书的核心思想——Code shoule be easy to understand。接着探讨什么是好代码,是内…
吴裕雄 10-MySQL插入数据
语法以下为向MySQL数据表插入数据通用的 INSERT INTO SQL语法:INSERT INTO table_name ( field1, field2,...fieldN ) VALUES ( value1, value2,...valueN );如果数据是字符型,必须使用单引号或者双引号,如:"value"。 通…