SystemV 共享内存

  • 进程间通信(interprocess communication——IPC)允许两个独立的进程进行数据交换,即相互发送数据和接收数据。进程间通信有两种基本模型:共享内存和消息传递。在共享内存模型中,建立了一个由协作进程共享的内存区域,然后,进程可以通过向共享区域读写数据来交换信息。在消息传递模型中,通信通过协作进程之间交换的消息进行。共享内存可能比消息传递更快,因为消息传递通常需要系统调用来实现,因此需要更耗时的内核干预任务。消息传递对于交换少量数据很有用,因为不需要避免冲突。在共享内存系统中,仅在建立共享内存区域时才需要系统调用。一旦建立了共享内存,所有访问都被视为例行内存访问,不需要内核的帮助。

  • 通过系统调用,将多个进程地址空间的部分区域映射到同一份物理内存,从而形成共享内存。共享内存具有最大的通信速度和便利性,因为它可以在计算机中以内存传输速度完成通信。然而,共享内存在多进程访问的同步和互斥方面存在问题,需程序员自行保证数据安全。

  • 进程运行结束,系统创建的IPC资源并不会释放,它的生命周期由内核决定。可以通过以下命令查看并手动释放:

    [test@VM-12-4-centos SystemVIPC]$ ipcs -m------ Shared Memory Segments --------
    key        shmid      owner      perms      bytes      nattch     status       # perms文件权限
    0x66010da7 0          test       664        4096       0                       [test@VM-12-4-centos SystemVIPC]$ ipcrm -m 0
    [test@VM-12-4-centos SystemVIPC]$ ipcs -m------ Shared Memory Segments --------
    key        shmid      owner      perms      bytes      nattch     status
    
  • SystemV 共享内存的系统调用:

  • 分配共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);

key:必须是IPC独立私有的值。可以通过ftok()生成

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);

失败返回-1;成功返回System V IPC key。当pathname和proj_id相同时,生成的key是相同的。

size:系统给共享内存分配的大小实际是PAGE_SIZE(4Kb)的整数倍。

shmflg: IPC_CREAT :存在则获取,不存在则创建一块新的内存区域; IPC_EXCL:与创建选项一起使用,若已经存在则创建失败,保证创建的共享内存是第一次创建的。

返回值:成功创建返回共享内存的ID;失败则返回-1。

  • 删除共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

cmd:IPC_RMID:删除共享内存

buf:shmid的data struct,用来描述共享内存的属性

  • 将共享内存与进程的虚拟地址空间进行挂接
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid, const void *shmaddr, int shmflg);

shmid:shmget()的返回值,为共享内存的ID(类似于数组下标)

shmaddr:虚拟地址空间的地址,设置为NULL会由操作系统进行分配。

shmflg:设0由操作系统管理。

返回值:成功返回共享内存的段地址——虚拟地址。

  • 将共享内存与进程解挂接
int shmdt(const void *shmaddr);

shmaddr:shmat()的返回值。

下面是一段例程说明SystemV共享内存的使用:

  • SharedPath.h
#pragma once#define PipeFilePath "PipeFile"
#define IPC_ID 0x1666
  • server.c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "SharedPath.h"
#include <sys/ipc.h>
#include <sys/shm.h>int main()
{key_t KeyVal = ftok(PipeFilePath, IPC_ID);if(KeyVal == -1){perror("ftok failed\n");exit(-1);}//int id = shmget(KeyVal, 4096, IPC_CREAT | IPC_EXCL | 0664); int id = shmget(KeyVal, 4096, IPC_CREAT | 0664); //在物理内存中开辟了一段共享空间if(id < 0){perror("shmget failed\n");exit(-2);}char* Virtualaddr = (char*)shmat(id, NULL, 0);// ************共享内存使用****************while(1){printf("%s\n", Virtualaddr); //读取fflush(stdout);sleep(1);if(Virtualaddr == NULL){break;}}//***************************************shmdt(Virtualaddr);shmctl(id, IPC_RMID, NULL); //释放共享内存空间return 0;
}
  • client.c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include "SharedPath.h"
#include <sys/ipc.h>
#include <sys/shm.h>int main()
{key_t KeyVal = ftok(PipeFilePath, IPC_ID);if(KeyVal == -1){perror("ftok failed\n");exit(-1);}int id = shmget(KeyVal, 4096, IPC_CREAT); //获取已存在的IPC ID。if(id < 0){perror("shmget failed\n");exit(-2);}char* Virtualaddr = (char*)shmat(id, NULL, 0);// ************共享内存使用****************int i = 0;while(1){for(i = 0; i < 10; i++){Virtualaddr[i] = 'a'; sleep(5);}Virtualaddr[i] = '\n'; Virtualaddr[i + 1] = '\0'; }//***************************************shmdt(Virtualaddr);return 0;
}
  • Makefile
.PHONY:all
all:client server
client:client.cgcc -o $@ $^server:server.cgcc -o $@ $^.PHONY:clean
clean:rm -f client server

SystemV 共享内存相关推荐

  1. SystemV 共享内存(一)—— 共享内存的创建与释放(shmget / shmctl)

    匿名管道和命名管道都是基于文件的进程间通信,SystemV方案是在OS内核层面专门为进程间通信设计的一个方案,然后通过系统调用(system call)给用户提供通信接口 SystemV方案包含三种: ...

  2. Linux进程间通信六 Posix 共享内存简介与示例

    1. 共享内存简介 共享内存主要用于不同进程之间相互通信,因为操作的是同一块地址,不需要内核和用户层之间数据拷贝,属于最快的进程间通信方式,不过,为了防止读写冲突,一般需要额外的同步手段.之前介绍了S ...

  3. 【Linux】进程间通信--systemV标准--共享内存

    文章目录 systemV 标准 共享内存通信原理 共享内存的理解 共享内存的创建--shmget函数 查看共享内存和释放共享内存方式 挂在共享内存--shmat函数 去挂在共享内存--shmdt函数 ...

  4. Linux四种共享内存技术(附源码):SystemV、POSIX mmap、memfd_create、dma-buf

    <Linux 下的进程间通信:管道.消息队列.共享文件.共享内存> <[共享内存]基于共享内存的无锁消息队列设计> <File Sealing & memfd_c ...

  5. Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存

    Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...

  6. Linux进程间通信一 System V 共享内存简介与示例

    目录 1. System V共享内存简介 2. API介绍 2.0 key_t和标识符 2.1  创建system v共享内存 2.2 映射共享内存并使用 2.3 取消共享内存映射 2.4 控制共享内 ...

  7. Linux下进程间通信方式之管道、信号、共享内存、消息队列、信号量、套接字

    /* 1,进程间通信 (IPC ) Inter-Process Communication比较好理解概念的就是进程间通信就是在不同进程之间传播或交换信息.2,linux下IPC机制的分类:管道.信号. ...

  8. 210307共享内存的读写

    目录 一.学习的知识点 systemV POSIX(可移植操作系统接口)是一种标准 共享内存的读写 二.上课没有听懂或者没有理解的地方 三.当天学习的收获 一.学习的知识点 systemV msgge ...

  9. Linux 进程间通信:管道、共享内存、消息队列、信号量

    进程间通信 管道 共享内存 消息队列 信号量 进程间通信 https://blog.csdn.net/qq_35423154/article/details/105294963 在之前的一篇博客中讲过 ...

  10. Linux进程间通信(四) - 共享内存

    共享内存的优势 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只 ...

最新文章

  1. 怎样把centos 6.2 系统里的网卡em1还原为eth0
  2. python 画漫画_在漫画中画一条直线,罗宾逊投影
  3. 看完这篇文章,我再也不怕面试官问「垃圾回收」了...
  4. 云小课 | 使用ROMA API,API管理从此不用愁
  5. DSSM算法-计算文本相似度
  6. 华为算法精英赛(题3:概率计算)
  7. css基础--滤镜特效
  8. tomcat反向代理,监控,性能优化详细步骤
  9. 2款QQ空间首页好看的psd源码
  10. 无法听到计算机发出的声音怎么办,为什么视频对方听不到我说话_电脑视频对方听不到声音的解决方法...
  11. 计算机语言中的计数器是什么,程序计数器的作用_程序计数器pc中存放的是什么...
  12. 什么是用户实体行为分析(UEBA)
  13. 宝塔面板网站nginx伪静态配置方法
  14. Redhat7 yum安装有问题+yum无法使用+There are no enabled repos. Run “yum repolist all“ to see the repos you ha
  15. 14. python-es-8.3.3-多词项聚合multi_terms
  16. 计算机镜像怎么恢复,教你如何在win7系统创建系统恢复镜像
  17. 云计算零基础(2)配置yum仓库
  18. 用selenium和BeautifulSoup爬取网易云音乐歌手id
  19. ESP01 连接OneNet平台
  20. DNS主从域名解析服务器

热门文章

  1. 常用字典代码推荐标准
  2. App后台开发架构实践
  3. 一个很有意思的熊猫免疫器
  4. 熟练的mescroll
  5. WPS简历模板的图标怎么修改_个人简历模板集锦,简历自我评价怎么写?
  6. selenium反爬
  7. 图片去水印工具:Inpaint 7.2中文专业破解版下载及使用方法
  8. uniapp怎么使用阿里矢量图标,阿里矢量图标下载,阿里矢量图标应用,改变iconfont,uniapp 引用阿里矢量图标
  9. 从零开始的机器人比赛(一)——项目准备篇
  10. JSONP原理以及示例