linux进程间通信:system V 信号量和共享内存实现进程间同步
关于信号量和共享内存的相关描述已经在前几篇提到过;
- 信号量:即内核维护的一个正整数,可以使用内核提供的p/v接口进行该正整数的+/-操作,它主要用来表示系统中可用资源的个数,协调各个进程有序访问资源,防止发生冲突
- 共享内存:操作系统从运行中的进程拥有的3G用户空间中提供一段用户态可以直接访问的内存块,并且该内存区域可以被其他进程共享
信号量在共享内存中的使用基本流程如下图:
两个信号量,一个用于控制读端进程对共享内存的访问,一个用于控制写端进程对共享内存的访问
当写端进程写入时,写信号量sem1 进程p操作,读信号量sem0进行v操作
当读端进程写入时,读信号量sem0进行p操作,写信号量sem1进程v操作
以下代码通过信号量实现了每次仅有一个进程操作共享内存
写端sem_write.c
:
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/types.h>union semnum {int val;struct semid_ds *buf;unsigned short int *array;struct seminfo *__buf;
};
int sem_id;//初始化信号量
void sem_init(int sem_id, int nsignum, int sem_value) {union semnum sem_union;sem_union.val = sem_value;if (semctl(sem_id,nsignum,SETVAL,sem_union) == -1) {printf("semctl failed\n");_exit(-1);}
}//对信号量进行p操作 -1
void sem_p(int sem_id, int nsignum) {struct sembuf sops;sops.sem_num = nsignum;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;if (semop(sem_id, &sops,1) == -1) {printf("semop P failed \n");_exit(-1);}}
//对信号量进行v操作 +1
void sem_v(int sem_id, int nsignum) {struct sembuf sops;sops.sem_num = nsignum;sops.sem_op = 1;sops.sem_flg = SEM_UNDO;if (semop(sem_id, &sops,1) == -1) {printf("semop P failed \n");_exit(-1);}
}//打印信号量
void sem_print(int sem_id, int nsignum) {int sem_value;sem_value = semctl(sem_id, nsignum, GETVAL);printf("sem[%d] = %d \n",nsignum, sem_value);
}int main() {int shm_id;key_t shm_key = ftok("./",111);key_t sem_key = ftok("./",112);//创建共享内存,并将共享内存进行映射,获取映射后的共享内存地址shm_id = shmget(shm_key , 1028 , IPC_CREAT | 0666);char *shm_addr = shmat(shm_id, NULL , 0);sem_id = semget(sem_key,2,IPC_CREAT | 0666);//创建两个信号量if(sem_id == -1) {sem_id = semget(sem_key, 2 ,0666);}else {sem_init(sem_id,0,0); //初始化读端信号量sem_init(sem_id,1,1); //初始化写端信号量}while(1) {sem_p(sem_id,1); //由于接下来要写入共享内存,则对写端信号量进行p操作,-1fgets(shm_addr,1020,stdin);sem_v(sem_id,0);//由于读进程在阻塞读,则写完之后立即将读信号量进行v操作}return 0;
}
读端sem_read.c
#include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/types.h>union semnum {int val;struct semid_ds *buf;unsigned short int *array;struct seminfo *__buf;
};
int sem_id;void sem_init(int sem_id, int nsignum, int sem_value) {union semnum sem_union;sem_union.val = sem_value;if (semctl(sem_id,nsignum,SETVAL,sem_union) == -1) {printf("semctl failed\n");_exit(-1);}
}void sem_p(int sem_id, int nsignum) {struct sembuf sops;sops.sem_num = nsignum;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;if (semop(sem_id, &sops,1) == -1) {printf("semop P failed \n");_exit(-1);}}void sem_v(int sem_id, int nsignum) {struct sembuf sops;sops.sem_num = nsignum;sops.sem_op = 1;sops.sem_flg = SEM_UNDO;if (semop(sem_id, &sops,1) == -1) {printf("semop P failed \n");_exit(-1);}
}void sem_print(int sem_id, int nsignum) {int sem_value;sem_value = semctl(sem_id, nsignum, GETVAL);printf("sem[%d] = %d \n",nsignum, sem_value);
}int main() {int shm_id;key_t shm_key = ftok("./",111);key_t sem_key = ftok("./",112);shm_id = shmget(shm_key , 1028 , IPC_CREAT | 0666);char *shm_addr = shmat(shm_id, NULL , 0);sem_id = semget(sem_key,2,IPC_CREAT | 0666);if(sem_id == -1) {printf("semget failed\n");_exit(-1);}else {sem_init(sem_id,0,0); //初始化读端信号量sem_init(sem_id,1,1); //初始化写端信号量}while(1) {//对读端信号量进行p操作,-1,接下来要从共享内存读sem_p(sem_id,0);printf("from shm:%s\n",shm_addr);//读完之后将写端信号量进行v操作,+1,因为还有写端进程需要写入(p操作),防止信号量变为-1sem_v(sem_id,1);}return 0;
}
输入如下:
相关文章:
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\…
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);函数参数&…