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. thinkphp5 chunk 分块处理数据小坑

    场景: 使用chunk方法进行分块查询写入数据,执行发现chunk分几条一次处理 数据库就插入几条,并没有return false; 代码如下 解决方法: 增加排序字段

  2. python实现自动生成小学四则运算题目(软工第二次项目作业)

    前言 软件工程 传送带 作业要求 传送带 作业目标 结对编程:代码实现.性能分析.异常处理说明.记录PSP表格 代码见: github 个人信息:朱育清 3118005437 信安二班 我的partn ...

  3. springmvc执行原理

    大家是否遇到过被面试官问了这样一句话:"来聊聊springmvc执行原理".是的,springmvc的执行流程是面试的高频点,今天我就来浅谈它! 一.下面通过一个简单的spring ...

  4. Jenkins+pytest+Allure搭建自动化测试

    持续集成(CONTINUOUS INTEGRATION) 在CI环境中,开发人员将会频繁地向主干提交代码.这些新提交的代码在最终合并到主干前,需要经过编译和自动化测试流进行验证. 持续交付(CONTI ...

  5. Linux给特定进程单独指定DNS

    Linux本身只能通过/etc/resolv.conf设置全系统的DNS.这里有一种给特定进程单独设置DNS的方法,通过免root的mount namespace达成.使用脚本只需要一条简洁的命令就可 ...

  6. spring boot: 用thymeleaf嵌套循环展示多层数据(spring boot 2.3.2)

    一,什么情况下会用到嵌套循环? 当我们展示多个分类时,每个分类下又展示出推荐的前几个商品,   这时我们需要用到嵌套循环 看一个例子: 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https:/ ...

  7. ansible使用setup模块查看受控机的信息(ansible2.9.5)

    一,ansible的setup模块的用途: 用来获取主机的信息 说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest 对应的 ...

  8. composer慢 设置阿里云镜像

    composer config -g repo.packagist composer https://mirrors.aliyun.com/composer

  9. mac 搭建 Robot Framework

    前提介绍,我的mac上python2和python3是都要有的,然后大家可以看看我其他的文章,这些文章虽然很多都是连接,是别人的博客或者资料,但都是自己试过没有问题的,只是比较懒然后就没有自己写. r ...

  10. 基于.Net Core开发的物联网平台 IoTSharp V1.5 发布

    很高兴的宣布新版本的发布, 这次更新我们带来了大量新特性, 最值得关注的是, 我们逐步开始支持分布式, 这意味着你可以通过多台服务器共同处理数据, 而不是原来的单机处理, 我们也将遥测数据进行分开存储 ...