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. git的项目完整操作

    今天来说下项目中git 的使用,针对常规操作: 然后执行  git status  可以看到目前的状态: 再执行添加操作      git add . 添加所有文件 接着执行提交命令  git com ...

  2. git fatal: Path 'XXX' is in submodule 'XXX'错误

    easyswoole项目的 vendor/easyswoole/socket/这个项目怎么都无法添加到git目录里面. 报错: Administrator@PhpServer MINGW64 /z/w ...

  3. Java 集合看这一篇就够了

    大家好,这里是<齐姐聊数据结构>系列之大集合. 话不多说,直接上图: Java 集合,也称作容器,主要是由两大接口 (Interface) 派生出来的: Collection 和 Map ...

  4. linux centos 03

    linux用户权限相关 root用户  相当于qq群的群主 sudo命令  相当于qq群的管理员 普通用户  相当于qq群的 水军 超级用户root的UID是 0  组ID也是 0  普通用户的UID ...

  5. spring boot:接收数组参数及多文件混合json参数(spring boot 2.3.4)

    一,生产环境中的复杂参数上传的场景 1,保存排序值 : 例如:某一件商品的多张展示图片排序,提交的排序值要和图片的id相对应 2,上传多张图片,图片要和指定的变量相对应 例如:在添加商品sku时, 需 ...

  6. swoft根据表创建实体

    php bin/swoft entity:gen table= table1,table2,table3,... [root@localhost swoft]# php bin/swoft entit ...

  7. MySQL锁详细讲解

    本文章向大家介绍MySQL锁详细讲解,包括数据库锁基本知识.表锁.表读锁.表写锁.行锁.MVCC.事务的隔离级别.悲观锁.乐观锁.间隙锁GAP.死锁等等,需要的朋友可以参考一下   锁的相关知识又跟存 ...

  8. 第十三章 Linux三剑客之老二—sed

    一.sed #擅长增删改查 替换 选项: -n #取消默认输出 -r #支持扩展正则使用 -i #改变文件内容 -e #允许多项编辑 内部指令: p #print 打印 d    # 删除 排除 a ...

  9. 洛谷 p6858 深海少女与胖头鱼 洛谷月赛 期望dp

    洛谷10月月赛 2 t2 深海少女与胖头鱼 题目链接 参考资料:洛谷10月赛2讲评ppt; 本篇题解考完那天就开始写,断断续续写到今天才写完 本题作为基础的期望dp题,用来学习期望dp还是很不错的 ( ...

  10. git学习(六) git reset操作

    git reset 操作 git reset git reset HEAD 文件名 移除不必要的添加到暂存区的文件 git reset HEAD^ 或者 commitid 去掉上一次的提交 git r ...