linux进程间通信:system V 信号量
文章目录
- 概念描述
- 通信原理
- 编程接口
- 使用流程
- 编程案例
概念描述
- 英文:
semaphore
简称SEM,主要用来进行进程间同步 - 本质:内核维护的一个正整数,可对其进行各种+/-操作
- 分类:systemV 信号量、POSIX 有名信号量、POSIX 无名信号量
- 用途:用来标示系统中可用资源的的个数,协调各个进程有序的访问资源,防止发生冲突
- P操作:程序在进入临界区之前要对资源进行申请
- V操作:程序离开临界区后要释放相应的资源
通信原理
- 类似于房卡,不是单个值,而是一组(实际上是数组)信号量元素构成
- 将信号量初始设置成一个绝对值
- 在信号量当前值的基础上加一个数量
- 在信号量当前值的基础上减去一个数量,降到0以下再去访问会引起阻塞
- 阻塞进程一直等待其他进程修改该信号量的值,直到恢复正常运行
- 信号量本身无意义,通常会与一块临界资源(共享内存)关联使用
编程接口
获取信号量ID
a. 头文件<sys/ipc.h> <sys/sem.h>
b.int semget(key_t key,int nsem, int semflg)
c. 函数参数:key:
用来表示信号量的键,通常使用值IPC_PRIVATE或者由ftok创建nsem
: 信号的数量,所有的信号量放在一个数组里semflg
:位掩码,用来设置信号量的权限或者检查一个已有信号量的权限
IPC_CREAT: 如果找不到指定的key相关联的信号量,创建一个信号量集合
IPC_EXCL: 若指定了IPC_CREAT且指定key相关联的信号量存在,报EXIST错误
d. 返回值
- 成功:返回操作信号量描述符
- 失败:返回-1
设置信号量
a. 头文件<sys/ipc.h> <sys/sem.h>
b.int semctl(int semid, int semnum, int cmd ..)
c. 函数参数:semid
: 信号量的描述符,标识符;用于操作信号量semnum
: 信号量的数量,所有的信号量放在一个数组内cmd
:
IPC_RMID :删除信号量及相关联的内核smid_ds数据结构
IPC_STAT: 获取semid_ds的副本
IPC_SET: 设置semid_ds的数据结构
GETVAL: 获取信号集中地 semnum个信号量的值
GETALL: 获取所有信号量的值
SETVAL: 设置信号集中的第semnum个信号量的值
d. 函数返回值
- 成功:根据cmd命令,返回不同的值
- 失败:-1
信号量P/V操作
a. 头文件<sys/ipc.h> <sys/sem.h>
b.int semop(int semid,struct sembuf *sops, size_t nsops);
c. 函数参数:semid
:信号的IPC标识符sops
: 指向数组的指针,数组中包含了需要执行的操作struct sembuf {unsigned short sem_num; // 标识要操作的信号集中的信号量/*sem_op如下信息:a.若大于0 将sem_op的值加到信号量值上b. 若等于0 ,则对信号量进行检查,确定其当前值是否为0,若为0则操作结束;若不为0,则一直阻塞,直到为0结束c. 若小于0,则将信号量值减去sem_op,最后结果大于或等于0,操作立即结束;若最后结果小于0,则当前进程会阻塞*/short sem_op;/*信号操作对标记,SEM_UNDO,IPC_NOWAIT*/short sem_flag; }
nsops
:数组的大小
d. 返回值
- 成功:根据cmd命令,返回不同的值
- 失败:-1,并设置errno全局变量
使用流程
- 使用semget 创建或打开一个信号量集
- 使用semctl SETVAL 或 SETALL 操作初始化集合中的信号量(其中一个进程操作即可,内核中维护,对其它进程是全局可见的)
- 使用semop操作信号量的值,多个进程通过多信号量值的操作来表示一些临界资源的获取和释放
- 当所有进程不再需要信号量集时,使用semctl IPC_RMID 操作删除这个信号量集(其中一个进程操作即可)
编程案例
sem_create.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>union semnum {int val;struct semid_ds *buf;unsigned short int *array;struct seminfo *__buf;
};int main ()
{int sem_id;key_t key;if ((key =ftok(".",111)) == -1) {printf("create key failed \n");_exit(-1);}//使用semget 创建或打开一个信号量集if ((sem_id = semget(key,3,IPC_CREAT | 0770)) == -1) {printf("create shm_id failed \n");_exit(-1);} printf("sem_id is :%d\n",sem_id);//获取信号量中的值int sem_value;sem_value = semctl(sem_id , 0, GETVAL);printf("sem value is %d\n",sem_value);//使用semctl SETVAL 或 SETALL 操作初始化集合中的信号量。通过sem_union设置信号量的值union semnum sem_union;sem_union.val = 2;semctl(sem_id, 0, SETVAL, sem_union);sem_value = semctl(sem_id ,0, GETVAL);printf("sem value after reset is %d\n",sem_value);//使用semop操作信号量,对信号量进行pv操作,这里是-1struct sembuf sops,sops2,sops3;sops.sem_num = 0;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;/*sops.sem_num = 1;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;sops.sem_num = 2;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;*/if( -1 == (semop(sem_id,&sops, 1)) ) {printf("semop set failed \n");_exit(-1);}sem_value = semctl(sem_id, 0, GETVAL);printf("sem value after semop is %d\n",sem_value);sleep(30);semctl(sem_id, 0 ,IPC_RMID);return 0;
}
最终的输出如下:
sem_id is :524314
sem value is 0
sem value after reset is 2
sem value after semop is 1
相关文章:
设计模式总结1
1.代码不是没有错误就是最好的 (1)命名要规范-------取一个好的名字。 (2)代码少做无用功。 (3)注意逻辑错误。 (4)面向对象:可维护、可复用、可扩展、灵活性好。 2.简单…
mysql 单选字段_mysql字段类型
学习自 https://www.cnblogs.com/jennyyin/p/7895010.html,感谢原博主的奉献mysql支持多种类型,大致可以分为三类:数值、字符串、日期/时间。数值类型类型大小范围(有符号)范围(无符号)用途tinyint1字节(-128, 127)(0,255)小整数值smallint2字…
ios时间差,以时间格式显示
为什么80%的码农都做不了架构师?>>> NSDate *nowDate [[NSDate alloc]init]; double diffTime [nowDate timeIntervalSinceDate:preDate]; int diffHour diffTime / (60*60); int diffMin ( diffTime - diffHour*(60*60) ) / (60); int diffSec…
深入理解C++中public、protected及private用法
深入理解C中public、protected及private用法 这篇文章主要介绍了C中public、protected及private用法,对于C面向对象程序设计来说是非常重要的概念,需要的朋友可以参考下初学C的朋友经常在类中看到public,protected,private以及它们在继承中表示的一些访问…
v-vim 代码批量缩进,字符串精确查找及替换
vim中代码批量缩进 有如下两种办法,主要依靠>和<字符来进行 缩进的单位通过设置~/.vimrc,添加如下行 set tabstop4 "设定tab宽度为4个字符 set shiftwidth4 "设定自动缩进为4个字符 set expandtab "用space替代tab的输入 set noexpandtab &q…
Codeforces Round #228 (Div. 1)B
进制构造 这里用了十进制 有点像串并联 每一位代表的数分开表示出来再把每一位的数并起来 比如892 就是800902 800又可分为8*10*10。。。 1 #include <iostream>2 #include<cstdio>3 #include<cstring>4 #include<algorithm>5 #include<stdlib.h&g…
javaweb实现mysql备份功能_java web 实现mysql 数据库备份、恢复
如题,由于项目需要,研究并实现了java web的 mysql数据库的备份、下载、恢复功能,中间遇到一些问题,耗费了不少时间,下面让我一一道来:背景介绍:window 7系统mysql 5.7eclipsespring mvctomcat 7…
在windows8 上安装framework 3.5
在电脑上装了windows8 的双系统后,为了装上Windows Live Writer,需要安装framework3.5.在线安装等了很久都装不上,下载的安装包不能用,提示需要framework3.5的支持。死循环啊 。搜索找到离线更新的方法, 离线更新方法&…
C#第一章笔记
第一个C#程序 namespace 是C#中组织代码的方式,它的作用那个类似java中的包 using 在Java中作用如果导入其他包 应该是用import关键字而在C#中应使用using关键字来引用 class关键字 与java一样C#也是一门面向对象的得语言,使用class关键字来表示类 Main&…
linux进程间通信:system V 信号量和共享内存实现进程间同步
关于信号量和共享内存的相关描述已经在前几篇提到过; 信号量:即内核维护的一个正整数,可以使用内核提供的p/v接口进行该正整数的/-操作,它主要用来表示系统中可用资源的个数,协调各个进程有序访问资源,防止…
mysql三次握手_一文彻底搞懂 TCP三次握手、四次挥手过程及原理
原创文章首发于公众号:「码农富哥」,欢迎收藏和关注,如转载请注明出处!TCP 协议简述TCP 提供面向有连接的通信传输,面向有连接是指在传送数据之前必须先建立连接,数据传送完成后要释放连接。无论哪一方向另…
【转】常见系统中文字体的英文名
http://www.aoao.org.cn/blog/2008/03/fonts-chinese/ http://www.yale.edu/chinesemac/pages/fonts.html Mac OS的一些: 华文细黑:STHeiti Light [STXihei]华文黑体:STHeiti华文楷体:STKaiti华文宋体:STSong华文仿宋&…
手动新增swap分区
1、建立1G的交换分区(填充) #dd if /dev/zore of /opt/swapfile bs1M count1024 2、设置交换分区文件 #mkswap /opt/swapfile 3、立即启用交换分区文件 #swapon /opt/swapfile 4、系统开机时自动挂载新分区 #vim /etc/fstab 末尾添加:/opt…
js捕获和冒泡
面向对象: 1.单例模式 2.工厂模式 3.构造函数 (1,2,3的目的都是生成对象) js天生自带的类 object(基类) 子类:function(函数) array(数组&…
linux进程间通信:system V 信号量 生产者和消费者模型编程案例
生产者和消费者模型: 有若干个缓冲区,生产者不断向里填数据,消费者不断从中取数据两者不冲突的前提: 缓冲区有若干个,且是固定大小,生产者和消费者各有若干个生产者向缓冲区中填数据前需要判断缓冲区是否满…
mysql类exadata功能_几类关系型数据库的数据解决方案
今天聊下几类关系型数据库的数据解决方案,算是抛砖引玉,近期也要对技术方向上做一些扩展,也算是前期的小结吧。13Oracle目前市面上的主流版本应该还是11gR2,记得很多年前有个网站做过一次调查,10g,11g的版本比例差不多…
ZOJ 2723 Semi-Prime ||ZOJ 2060 Fibonacci Again 水水水!
两题水题: 1.如果一个数能被分解为两个素数的乘积,则称为Semi-Prime,给你一个数,让你判断是不是Semi-Prime数。 2.定义F(0) 7, F(1) 11, F(n) F(n-1) F(n-2) (n>2) 让你判断第n项是否能被3整除。 1.ZOJ 2723 Semi-Prime ht…
Lua中的基本函数库
基本函数库为Lua内置的函数库,不需要额外装载assert (v [, message])功能:相当于C的断言,参数:v:当表达式v为nil或false将触发错误,message:发生错误时返回的信息,默认为"assertion failed…
Oracle中的substr()函数 详解及应用
1)substr函数格式 (俗称:字符截取函数) 格式1: substr(string string, int a, int b); 格式2:substr(string string, int a) ; 解释: 格式1: 1、string 需要截取的字符串 2、a 截取字符串…
linux进程间通信:POSIX 消息队列
文章目录基本介绍相关编程接口编程实例消息队列通信实例消息队列属性设置实例基本介绍 关于消息队列的基本介绍,前面在学习system V的消息队列时已经有过了解,linux进程间通信:system V消息队列 支持不同进程之间以消息(message…
opencv 修改图像数值_opencv 修改图像数值_Python中使用OpenCV读取像素
如何在Python中遍历像素呢?请看代码:import numpy as npimport cv2import matplotlib.pyplot as pltsrc cv2.imread("src.png")gray cv2.cvtColor(src, cv2.COLOR_RGB2GRAY)rows, cols gray.shape[:2]row gray[200]plt.plot(row)# plt.sho…
SQL中返回一个字符串在另一个中存在的次数
ALTER FUNCTION [reg].[f_GetSameStringCntNoSort] ( str1 VARCHAR(100),--源字符串,取该串中的strLen长度的字符是否在目的字符串 str2 VARCHAR(100) --目的字符串 ) RETURNS INT AS BEGIN -- 返回的长度 DECLARE count INT DECLARE returnValue …
自由软件的自由
我相信我的订阅者中有很多是IT从业人员,我们在工作中会使用各种软件,除了微软、苹果等软件巨头的商业软件,还有更多的自由软件。我们使用这些软件构建自己的工作环境,为公司开发运营系统,为客户实现业务流程࿰…
c/c++ 拷贝控制 构造函数的问题
拷贝控制 构造函数的问题 问题1:下面①处的代码注释掉后,就编译不过,为什么??? 问题2:但是把②处的也注释掉后,编译就过了,为什么??? …
linux进程间通信:POSIX 消息队列 ----异步通信
在上一篇中linux进程间通信:POSIX 消息队列我们知道消息队列中在消息个数达到了队列所能承载的上限,就会发生消息的写阻塞。 阻塞式的通信影响系统效率,进程之间在通信收到阻塞时并不能去做其他事情,而是一直处于阻塞状态。 为了…
【转】Android设计中的.9.png
来源:http://isux.tencent.com/android-ui-9-png.html Android设计中的.9.png 注意:当使用9.png做TextView背景时,一定要设置内容区域(底部和右侧),否则,文字显示不出来。 偶米伽 2013.08.20在A…
python创建scrapy_Python爬虫教程-31-创建 Scrapy 爬虫框架项目
首先说一下,本篇是在 Anaconda 环境下,所以如果没有安装 Anaconda 请先到官网下载安装Scrapy 爬虫框架项目的创建0.打开【cmd】1.进入你要使用的 Anaconda 环境1.环境名可以在【Pycharm】的【Settings】下【Project:】下找到2.使用命令&#…
KOAProgressBar
2019独角兽企业重金招聘Python工程师标准>>> KOAProgressBar 是 iOS 上的一个进度条控件,要求 iOS 5 支持 转载:http://www.adobex.com/ios/source/details/00000866.htm 转载于:https://my.oschina.net/u/868244/blog/106310
linux进程间通信:POSIX信号量
文章目录概念描述编程接口注意事项编程案例信号量基本接口使用案例信号量父子进程间通信信号量实现 两进程之间通信概念描述 英文:semaphore 简称SEM,主要用来进行进程间同步本质:内核维护的一个正整数,可对其进行各种/-操作分类…
指针小白:修改*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\…