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之共享内存的更多相关文章

  1. Linux 共享内存详解一

    共享内存段被多个进程附加的时候,如果不是所有进程都已经调用shmdt,那么删除该共享内存段时,会出现一个临时的不完整的共享内存段(key值是0),无法彻底删除.只有当所有进程都调用shmdt,这个临时 ...

  2. PHP进程通信基础——信号量+共享内存通信

    PHP进程通信基础--信号量+共享内存通信 由于进程之间谁先执行并不确定,这取决于内核的进程调度算法,其中比较复杂.由此有可能多进程在相同的时间内同时访问共享内存,从而造成不可预料的错误.信号量这个名 ...

  3. C++ 共享内存 函数封装

    #pragma once #include <string> #include <wtypes.h> #include <map> using namespace ...

  4. Linux学习笔记(14)-进程通信|共享内存

    在Linux中,共享内存是允许两个不相关的进程访问同一个逻辑内存的进程间通信方法,是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式. 不同进程之间共享的内存通常安排为同一段物理内存.进程可 ...

  5. linux 共享内存 shmat,shmget,shmdt,shmctl

    shmget int shmget(key_t key, size_t size, int flag);//开辟一段共享内存 key_t key :标识符的规则() size_t size :共享内存 ...

  6. Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()

    下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...

  7. linux后台查看共享内存和消息队列的命令

    ipcs ipcs -q : 显示所有的消息队列 ipcs -qt : 显示消息队列的创建时间,发送和接收最后一条消息的时间 ipcs -qp: 显示往消息队列中放消息和从消息队列中取消息的进程ID ...

  8. c++共享内存(转载)

    对于连个不同的进程之间的通信,共享内存是一种比较好的方式,一个进程把数据发送到共享内存中, 另一个进程可以读取改数据,简单记录一下代码 #define BUF_SIZE 256 TCHAR szNam ...

  9. OpenMP共享内存并行编程详解

    实验平台:win7, VS2010 1. 介绍 平行计算机可以简单分为共享内存和分布式内存,共享内存就是多个核心共享一个内存,目前的PC就是这类(不管是只有一个多核CPU还是可以插多个CPU,它们都有 ...

随机推荐

  1. 实验四  CSS样式的应用

    实验四  CSS样式的应用 注意:以下实验项目皆以本文件为操作对象,实验结果用记事本保留后预览,最后将添加的CSS代码转载到实验报告中 另本网页中蓝色加下划线的字即为默认的超链接样式 实验目的: 掌握 ...

  2. 多测师讲解自动化测试 _如何解决验证码的问题_高级讲师肖sir

    自动化测试如何解决验证码的问题对于web应用来说,大部分的系统在用户登录时都要求用户输入验证码,验证码的类型的很多,有字母数字的,有汉字的,甚至还要用户输入一条算术题的答案的,对于系统来说使用验证码可 ...

  3. 【转】了解nodejs、javascript间的关系!bom&dom&ecmascript

    地址:https://www.cnblogs.com/JetpropelledSnake/p/9450810.html bom&dom:https://www.cnblogs.com/wang ...

  4. MeteoInfoLab脚本示例:站点数据绘制等值线

    站点数据绘制等值线需要首先将站点数据插值为格点数据,MeteoInfo中提供了反距离权法(IDW)和cressman两个方法,其中IDW方法可以有插值半径的选项.这里示例读取一个MICAPS第一类数据 ...

  5. spring boot:spring security给用户登录增加自动登录及图形验证码功能(spring boot 2.3.1)

    一,图形验证码的用途? 1,什么是图形验证码? 验证码(CAPTCHA)是"Completely Automated Public Turing test to tell Computers ...

  6. Martyr2项目实现——Number部分问题求解(3) Prime Factorization

    Martyr2项目实现--Number部分问题求解(3) Prime Factorization 质因子分解 问题描述: Prime Factorization – Have the user ent ...

  7. 数组列表(ArrayList)

    2020-10-20        longzqa@163.com        stronglzq [摘要]针对数组容量固定无法扩展的问题,引入数组列表(ArrayList).主要对数组列表的声明及 ...

  8. Spring Cloud Alibaba Sentinel

    一.介绍(sentinel 1.7.0) 1,官网地址 https://github.com/alibaba/Sentinel 中文地址:https://github.com/alibaba/Sent ...

  9. day04基本数据类型

    内容补充 编译器和解释器:牵扯到编译型语言和解释型语言 编译型语言:JAVA C C# C++ 写好的代码交给编译器,编译器会编译成一个新的文件交给计算机执行 解释型语言:python PHP 写好的 ...

  10. 感知机vs支持向量机

    感知机原理:二维空间中找到一条直线可以把所有二元类别分离开,三维或多维空间中,找到一个分离超平面把所有二元类别分离开.而可把所有二元类别分离开的超平面不止一个,哪个是最好的呢?损失函数:所有误分类的点 ...