UnixIPC之共享内存
Unix-IPC之共享内存
一,共享内存的概念
共享内存通信技术是一种最快的可用IPC形式,它是针对其他通信机制运行效率低和设计的新型通信技术(其他的如:信号量,管道,套接字等)。这种通信技术往往与其他通信机制(如信号量)结合使用,用于达到进程间的同步及互斥。
原理:
这种方式是在所有进程的独立空间之外开辟一块内存空间,它不属于任何一个进程,当所有进程都可以访问。利用这样的共享特性,发送进程就可以往共享区域中写入数据,而接收进程则可以从共享区域中获取所需信息。
采用共享内存的进程通信的特点:
- 进程通信中,需要交互的数据或消息不发生存储移动。
- 当需要交互时,通信进程双方通过共享内存区域完成信息交互。
- 对于共享内存区,可以用虚拟映射方式将其作为交互进程的内存使用。
二,相关系统调用
共享内存区的建立
Unix中通系统调用shmget()来建立一块共享内存,函数定义:
int shmget(key_t key, int size, int flag);
参数说明:
- key:表示共享内存的标识符
- size:共享内存以字节为单位的最小值,如果创建的是一个新共享区必须指定size,若使用已有的共享内存则size指定为0
- flag:是构成共享区标识的参照值
- 返回值:若要建立的共享区(传入的标识符)已存在,返回共享区描述符shmid,若不存在则先建立共享区在返回描述符
共享区的操作
Unix中使用shmctl系统调用查询共享区的状态信息,如大小、所链接的进程数、创建者标识符等。也可以修改其属性,还可以用来对共享区进行加锁或解锁。函数定义:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
参数说明
- shmid:是共享区的标识符
- cmd:表明在shmid指定的存储区可以执行以下命令:
IPC_STAT 对此段取shmid_ds结构存放在buf指向的结构中
IPC_SET 按buf指向的结构中的值设置此段相关的三个字段
IPC_RMID 从系统中删除该共享区
SHM_LOCK 对该共享区进行锁定,此命令只能有超级用户使用
SHM_UNLOCK 解锁该共享区,此命令只能由超级用户使用
共享区的链接
一但建立了共享区或获得了一个已有共享区的描述符后,就可以利用系统调用将该共享区链接到用户指定的某个进程的虚拟地址shmaddr上,并指定该存储区的访问属性(只读,还是可读可写)。此后进程就可以像对其他虚拟地址一样来访问该存储区。函数定义:
void *shmat(int shmid, void *addr, int flag);
共享区链接到调用进程的哪个地址上与调用函数中的addr参数和在flag中是否指定SHM_RND位有关:
- addr为0,此段链接由内核选择的第一个可用地址上
- addr非0,且未指定SHM_RND,此段链接到addr所指定的地址上
- addr非0,且指定了SHM_RND,此段链接到(addr-(addr mod SHMLBA))所表示的地址上
进程和共享区断开
当进程不需要共享内存时,可以利用系统调用shmdt()把该区与进程断开。但是shmdt()函数并不会删除共享区。
int shmdt(void *addr);
这里参数addr是shmat()调用的返回值。
三,实验
实验思路就是先在主进程中创建共享区并写入数据,再利用fork()系统调用创建一个子进程,子进程链接上共享区从中读取数据。代码如下:
//3 head file about share memory
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
//head file about process : fork() wait()
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#define SHM_MODE (SHM_R | SHM_W)
#define SHM_SIZE 2048
#define MSG "Hello, son process!"
int main(){
int segment_id;
char *shared_memory;
pid_t pid;
//creat share memory
if( (segment_id=shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE))<0 ) perror("shmget error!\n");
//main process link to share memory
if( (shared_memory=shmat(segment_id, 0, 0)) == (void *)-1 ) perror("shmat error!\n");
//man process send the mesg
sprintf(shared_memory, MSG);
printf("main process send message:%s\n",&MSG);
//man process unlink to share memory
shmdt(shared_memory);
pid=fork();
if(pid<0){
perror("fork error:");
}
else if(pid==0){
printf("I am son process!\n");
if( (shared_memory=shmat(segment_id, 0, 0)) == (void *)-1 ) perror("shmat error!\n");
printf("son process get the message:%s\n",shared_memory);
shmdt(shared_memory);
}
else{
printf("I am main process!\n");
wait(NULL);
shmctl(segment_id, IPC_RMID, 0);
}
return 0;
}
输出结果:
main process send message:Hello, son process!
I am main process!
I am son process!
son process get the message:Hello, son process!
UnixIPC之共享内存的更多相关文章
- Linux 共享内存详解一
共享内存段被多个进程附加的时候,如果不是所有进程都已经调用shmdt,那么删除该共享内存段时,会出现一个临时的不完整的共享内存段(key值是0),无法彻底删除.只有当所有进程都调用shmdt,这个临时 ...
- PHP进程通信基础——信号量+共享内存通信
PHP进程通信基础--信号量+共享内存通信 由于进程之间谁先执行并不确定,这取决于内核的进程调度算法,其中比较复杂.由此有可能多进程在相同的时间内同时访问共享内存,从而造成不可预料的错误.信号量这个名 ...
- C++ 共享内存 函数封装
#pragma once #include <string> #include <wtypes.h> #include <map> using namespace ...
- Linux学习笔记(14)-进程通信|共享内存
在Linux中,共享内存是允许两个不相关的进程访问同一个逻辑内存的进程间通信方法,是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式. 不同进程之间共享的内存通常安排为同一段物理内存.进程可 ...
- linux 共享内存 shmat,shmget,shmdt,shmctl
shmget int shmget(key_t key, size_t size, int flag);//开辟一段共享内存 key_t key :标识符的规则() size_t size :共享内存 ...
- Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()
下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...
- linux后台查看共享内存和消息队列的命令
ipcs ipcs -q : 显示所有的消息队列 ipcs -qt : 显示消息队列的创建时间,发送和接收最后一条消息的时间 ipcs -qp: 显示往消息队列中放消息和从消息队列中取消息的进程ID ...
- c++共享内存(转载)
对于连个不同的进程之间的通信,共享内存是一种比较好的方式,一个进程把数据发送到共享内存中, 另一个进程可以读取改数据,简单记录一下代码 #define BUF_SIZE 256 TCHAR szNam ...
- OpenMP共享内存并行编程详解
实验平台:win7, VS2010 1. 介绍 平行计算机可以简单分为共享内存和分布式内存,共享内存就是多个核心共享一个内存,目前的PC就是这类(不管是只有一个多核CPU还是可以插多个CPU,它们都有 ...
随机推荐
- js 递归的理解
友情提示:阅读本文需花 3分钟左右! 递归函数必须接受参数. (比如我要递归谁?) 在递归函数的定义初始,应该有一个判断条件,当参数满足这个条件的时候,函数停止执行,并返回值.(指定退出条件,否则就会 ...
- 要是想让程序跳转到绝对地址是0x100000去执行
要对绝对地址0x100000赋值,我们可以用 (unsigned int*)0x100000 = 1234; 那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做? *((void (* ...
- Dotnet Core使用特定的SDK&Runtime版本
Dotnet Core的SDK版本总在升级,怎么使用一个特定的版本呢? 假期过完了,心情还在.今天写个短的. 一.前言 写这个是因为昨天刷微软官方文档,发现global.json在 SDK 3.0 ...
- vi/vim系统编辑命令使用技巧
01前言 在Linux系统中会有很多的文件信息,这些文件的内容如果需要编辑,就必须借助vi或vim编辑命令. vi是Linux命令行界面下的重要文字编辑器.vim是vi命令的增强版. [语法格式] v ...
- 无法访问GitHub
我们开发者经常用的最大的同性交流平台--GitHub忽然访问不了了,很尴尬 可以打开控制台 ping一下 github.com 果不其然 不通 不过幸运的是里面有github的ip地址,好像是美国某个 ...
- 带权二分图最大匹配KM算法
二分图的判定 如果一个图是连通的,可以用如下的染色法判定是否二分图: 我们把X部的结点颜色设为0,Y部的颜色设为1. 从某个未染色的结点u开始,做BFS或者DFS .把u染为0,枚举u的儿子v.如果v ...
- Pyrhon-OS库
import os 导入OS模块 print(os.getcwd()) #获取当前路径 print(os.listdir()) #当前路径下文件信息 关于路径 Windows 下的路径采用 (\) 在 ...
- Unity实现代码控制音频播放
前言 很久没说过Unity了,现在说一下Unity用代码控制音频播放 准备工作 1.需要播放的音频 2.给需要加声音的对象加Audio Source组件 3.新建Play脚本,并绑定需要播放声音的对象 ...
- 记一次flink入门学习笔记
团队有几个系统数据量偏大,且每天以几万条的数量累增.有一个系统每天需要定时读取数据库,并进行相关的业务逻辑计算,从而获取最新的用户信息,定时任务的整个耗时需要4小时左右.由于定时任务是夜晚执行,目前看 ...
- maven 是什么