Linux共享存储通信

内容

  • 创建共享存储区实现进程通信

机理说明

共享存储区(Share Memory)是Linux系统中通信速度最高的通信机制。该机制中共享内存空间和进程的虚地址空间满足多对多的关系。即一个共享内存空间可以映射多个进程的虚地址空间,一个进程的虚地址空间又可以连接多个共享存储区。当进程间预利用共享存储区通信时,先要在主存中建立一个共享存储区,然后将它附接到自己的虚地址空间。该机制只为进程提供了用于实现通信的共享存储区和对共享存储区进行操作的手段,然而并未提供对该区进行互斥访问及进程同步的措施

调用函数说明

创建共享内存

shmget(key ,size ,flag)

功能:获得一个内部标识为shmid的共享存储区。

语法:int shmget = int shmget(key_t key ,int size ,int flag);

参数说明:

​ key 共享存储区关键字,可由用户指定。若使用IPC_PRIVATE则其值由系统产生。

​ size 存储区大小(字节数)。若存储区定义为字符型,则大小为定义的字符个数;若定义为整型,大小可以用sizeof(int)加以定义

​ flag 用户设置的标志或访问方式,如0666|IPC_CREAT,表示任意进程皆可读可写

操作允许权 八进制数 操作允许权 八进制数
用户可读 0400 小组可写 0020
用户可写 0200 其它可读 0004
小组可读 0040 其它可写 0002

附接共享内存

字符型共享内存:

shmat(int shmid ,char *shmadddr ,int msgflg ,ulong * raddr);

数值型共享内存:

shmat(int shmid ,int *shmadddr ,int msgflg ,ulong * raddr);

语法格式:

字符型共享内存:

viraddr = (char *) shmat (shmid ,shmaddr ,shmflag);

viraddr = (int *) shmat (shmid ,shmaddr ,shmflag);

参数说明:

​ shmid共享存储区的描述符,可由shmget()的返回值得到。

​ shmaddr用户提供的共享存储区附接的虚地址。

​ shmflag规定存储区的操作权限。如,SHM_RND则表示操作系统在必要时舍去地址;SHM_RDONLY则表示只允许读,shmflag为0表示可读可写。

断开共享内存

shmdt(viraddr)

参数说明:

​ viraddr系统调用shmat()所返回的虚地址。

返回值:

​ 函数被正确调用则返回0,错误返回-1

shmctl(int shmid ,int cmd ,struct shmid_ds * buf);

功能:对共享内存进行操作控制

参数说明:

​ shmid共享存储区的描述符,可由shmget()的返回值得到。

​ buf用户级数据结构地址,可为0。

​ cmd规定的操作类型

操作代码 含义
IPC_STAT 返回指定shmid数据结构的状态信息,放置于*buf中,必须有读取允许权
IPC_SET 设置指定shmid的有效用户和操作存取权
IPC_RMID 删除指定shmid以及与它相关的共享存储区的数据结构
SHM_LOCK 在内存中锁定指定的共享存储区,必须是root才能执行

shmctl(shmid ,IPC_RMID ,0); //撤销共享内存区

实现思路

send:

  • shmget()创建或者获取指定key值的共享内存
  • shmat()将该内存附接到自己的虚拟地址空间
  • 将消息写入共享内存
    • 字符:

      • 以追加方式写入,strcat(viraddr ,buffer)
      • 以覆盖方式写入,strcpy(viraddr ,buffer)
    • 数字:
      • 直接赋值
      • 操作数组\
  • shmdt()断开共享内存

receive:

  • shmget()创建或者获取指定key值的共享内存
  • shmat()将该内存附接到自己的虚拟地址空间
  • 输出信息
  • shmdt()断开共享内存
  • shmctl()撤销内存

实例

send

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
/*共享内存 share memory 实现的进程通信*/
main()
{
int shmid;
char *viraddr;
char buffer[BUFSIZ]; shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT);
viraddr=(char*)shmat(shmid,0,0); while(1)
{
puts("Enter some text:");
fgets(buffer,BUFSIZ,stdin);/*从标准输入设备读入一行字符串,stdin是标准输入,C标准库里面的一 个全局变量*/
strcat(viraddr,buffer); /*字符串追加函数*/
if(strncmp(buffer,"end",3)==0)/*比较两个字符串数组*/
break;
}
shmdt(viraddr);
exit(0);
}

receive

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h> main()
{
int shmid;
char *viraddr; shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT);
viraddr=(char*)shmat(shmid,0,0); printf("Your message is :\n%s",viraddr);
shmdt(viraddr); /*断开连接*/
shmctl(shmid,IPC_RMID,0); /*撤销共享内存*/
exit(0);
}

运行结果

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/shm.h>
/* 父进程与子进程间的通信,子进程写信息到共享内存中,父进程读取该信息
BUFSIZ为全局量定义在<stdlib.h>,8192
使用exit(0)和wait(0)进行同步*/
main()
{
int chld,shmid;
char *viraddr;
char buffer[BUFSIZ]; shmid=shmget(IPC_PRIVATE,BUFSIZ,0666|IPC_CREAT);
viraddr=(char*)shmat(shmid,0,0); while((chld=fork())==-1);
if(chld==0)
{ /*子进程块*/
while(1)
{
puts("Enter some text:"); /*写信息到共享内存*/
fgets(buffer,BUFSIZ,stdin); /*用户输入信息*/
strcat(viraddr,buffer); /*附接到进程的虚拟空间*/
if(strncmp(buffer,"end",3)==0)
break; /*输入end结束*/
}
exit(0);
}
else
{ /*父进程块*/
wait(0);
printf("Your message is:\n%s",viraddr); shmdt(viraddr); /*断开共享内存*/
shmctl(shmid,IPC_RMID,0); /*释放共享内存*/
exit(0);
}
}

运行结果

Linux-共享内存通信的更多相关文章

  1. linux 两个进程通过 共享内存 通信例子

    例子1:两个进程通过共享内存通信,一个进程向共享内存中写入数据,另一个进程从共享内存中读出数据 文件1 创建进程1,实现功能,打印共享内存中的数据 #include <stdio.h> # ...

  2. 【转载】ipcs与Linux共享内存

    一.共享内存相关知识 所谓共享内存,就是多个进程间共同地使用同一段物理内存空间,它是通过将同一段物理内存映射到不同进程的 虚拟空间来实现的.由于映射到不同进程的虚拟空间中,不同进程可以直接使用,不需要 ...

  3. Linux 程序设计1:深入浅出 Linux 共享内存

    笔者最近在阅读Aerospike 论文时,发现了Aerospike是利用了Linux 共享内存机制来实现的存储索引快速重建的.这种方式比传统利用索引文件进行快速重启的方式大大提高了效率.(减少了磁盘 ...

  4. linux 共享内存shm_open实现进程间大数据交互

    linux 共享内存shm_open实现进程间大数据交互 read.c #include <sys/types.h> #include <sys/stat.h> #includ ...

  5. Linux共享内存(二)

    Linux共享内存编程实例 原文链接:http://blog.csdn.net/pcliuguangtao/article/details/6526119 /*共享内存允许两个或多个进程进程共享同一块 ...

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

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

  7. Linux 共享内存编程

    共享内存允许系统内两个或多个进程共享同一块内存空间,并且数据不用在客户进程和服务器进程间复制,因此共享内存是通信速度最快的一种IPC. 实现的机制简单描述如下:一个进程在系统中申请开辟了一块共享内存空 ...

  8. Windows进程间共享内存通信实例

    Windows进程间共享内存通信实例 抄抄补补整出来 采用内存映射文件实现WIN32进程间的通讯:Windows中的内存映射文件的机制为我们高效地操作文件提供了一种途径,它允许我们在WIN32进程中保 ...

  9. linux 共享内存

    共享内存是最高效的IPC机制,因为它不涉及进程之间的任何数据传输.这种高效带来的问题是,我们必须用其他手段来同步进程对共享内存的访问,否则会产生竞态条件.所以,共享内存通常和其他进程间通信方式一起使用 ...

  10. linux使用共享内存通信的进程同步退出问题

    两个甚至多个进程使用共享内存(shm)通信,总遇到同步问题.这里的“同步问题”不是说进程读写同步问题,这个用信号量就好了.这里的同步问题说的是同步退出问题,到底谁先退出,怎么知道对方退出了.举个例子: ...

随机推荐

  1. Spring Cloud中关于Feign的常见问题总结

    一.FeignClient接口,不能使用@GettingMapping 之类的组合注解 代码示例: @FeignClient("microservice-provider-user" ...

  2. 页面循环绑定(变量污染问题),js面向对象编程(对象属性增删改查),js字符串操作,js数组操作

    页面循环绑定(变量污染问题) var lis = document.querySelectorAll(".ul li") for ( var i = 0 ; i < lis. ...

  3. luogu P5323 [BJOI2019]光线

    传送门 先考虑\(n=1\)的情况不是输入数据都告诉你了吗 然后考虑\(n=2\),可以光线是在弹来弹去的废话,然后射出去的光线是个等比数列求和的形式,也就是\(x_1\sum_{i=1}^{\inf ...

  4. 关于JDK1.7+中HashMap对红黑树场景的思考

    背景 在1.7之前的版本,当数组元素较多(几百.几千,或者更多)的时候,在这种前提扩容,涉及全量元素的遍历和坐标的重新定位,这个耗时会比较长.这是之前存在的一个弊端吧.那么引入红黑树之后就解决了问题, ...

  5. 干掉windows无脑设定:“始终使用选择的程序打开这种文件”、“使用Web服务查找正确的程序”

    先看几张图体会一下: 实在很佩服自己就那样默默忍受了很多很多年.其实这些东西在网上小小的一搜,5分钟就能搞定. 然而我们大家都在想,现在没时间,我还要做xxxx事呢,反正多点两下鼠标而已. 是啊,点两 ...

  6. Python自动化中的元素定位xpath(二)

    1.Xpath元素定位 1)ele = b.find_element_by_xpath(‘/html/body/from/input[1]’) 2)Ele = b.find_element_by_xp ...

  7. CentOs7.5安装Redis

    前言 虽说现在都是买服务了,可是自己做的小DEMO偶尔也用用Redis,不会装也不行 变更记录 # 19.4.24  起笔 正文 官网 https://redis.io/ 首先去官网找到最新的链接 截 ...

  8. MyOD(课下作业,选做)

    MyOD(课下作业,选做) 代码要求 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能,要求MyCP支持两个参数: java MyCP -tx XXX1.txt XXX2.b ...

  9. js-图片预加载

      //图片预加载 //闭包模拟局部作用于 (function($){ function Preload(imgs,options){ this.imgs = (typeof imgs === 'st ...

  10. CleanWebpackPlugin 低版本失效

    解决这个问题只需要 升级至2.0.1版本就行  不需要传参