进程间通信之System V 共享内存

文章目录

  • 一、共享内存

进程具有独立性,因此进程间通信的前提是两个进程能看到同一份资源

一、共享内存

在内存中申请一块空间,并将起始地址分别映射到两个进程的虚拟地址空间上,便可以让两个进程看到同一份资源

在这里插入图片描述

操作系统为了管理共享内存,除了创建共享内存外,还会创建包含共享内存信息的结构体

系统调用 shmget,头文件 sys/ipc.h、sys/shm.h

// 创建或获取共享内存
int shmget(key_t key, size_t size, int shmflg)

返回值:返回共享内存标识符 (供用户使用),出错返回 -1,并且 errno 被设置为相应的出错信息

参数:

  • key 用于创建或获取共享内存
    由于进程具有独立性,为了让两个进程可以找到同一个共享内存,通信双方的进程约定,创建共享内存的进程将 key 值设置到共享内存对应的结构体中,获取共享内存的进程通过相同的 key 来查找共享内存

  • size 表示共享内存的大小
    操作系统实际申请的共享内存大小为 size 向上调整到 PAGE_SIZE(4KB) 的整数倍

  • shmflag 位图,传递多个标志位时,标志位之间用 | 连接

常用的标志位:

  • IPC_CREAT 表示如果 key 值对应的共享内存不存在则创建,存在则获取
  • IPC_EXCL 不能单独使用,需要和 IPC_CREAT 一起传,表示如果 key 值对应的共享内存不存在则创建,存在则出错,即保证获取的共享内存一定是最新的
  • 0ddd 八进制数,表示共享内存的拥有者、所属组及 other 的操作权限

系统调用 ftok,头文件 sys/types.h、sys/ipc.h,生成创建共享内存时所需要的 key 值

// key_t 类型就是 int 的 typedef
key_t ftok(const char *pathname, int proj_id)

系统调用 shmat / shmdt,头文件 sys/types.h、sys/shm.h

// 将标识符为 shmid 的共享内存与进程虚拟地址 shmaddr 关联,如果 shmaddr 指定 NULL,表示由操作系统自主决定与进程关联的虚拟地址
// shmflg 指定 0 表示以读写方式关联共享内存,指定 SHM_RDONLY 表示以读方式关联共享内存,不存在以写方式关联共享内存,此时进程必须具有共享内存相应的操作权限
// 成功返回与共享内存关联的虚拟地址,失败返回 (void*) -1
void *shmat(int shmid, const void *shmaddr, int shmflg)// 解除进程虚拟地址 shmaddr 和共享内存的关联
// 成功返回 0,失败返回 -1
int shmdt(const void *shmaddr)

共享内存的生命周期随操作系统,因此创建共享内存的进程退出后,并不会删除共享内存,需要通过系统调用或者指令删除共享内存

系统调用 shmctl,头文件 sys/ipc.h、sys/shm.h

// 对标识符为 shmid 的共享内存执行 cmd 指定的操作,buf 用来设置或者获取共享内存的属性,不需要则指定为 NULL
// cmd 指定 IPC_RMID 表示将共享内存标记为销毁,当共享内存的关联数为 0 时,共享内存会自动销毁
// 成功返回 0,失败返回 -1
int shmctl(int shmid, int cmd, struct shmid_ds *buf)

server 从共享内存中读取,client 向共享内存中写入

// shm.hpp
#ifndef __SHARED_MEMORY__
#define __SHARED_MEMORY__#include <iostream>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>#define PATHNAME "."
#define PROID 0x666
#define CREATSHM (IPC_CREAT | IPC_EXCL)
#define GETSHM IPC_CREAT
#define CREAT 0 // 创建者
#define GET 1 // 获取者const size_t gsize = 4096;namespace starrycat
{class SharedMemory{public:SharedMemory(int flag, mode_t mode, size_t size = gsize, const char *pathname = PATHNAME, int proid = PROID): _type((flag == CREATSHM) ? CREAT : GET){umask(0);// 生成唯一的 keykey_t key = ftok(pathname, proid);if (key < 0){std::cout << "key 生成失败: " << errno << " " << strerror(errno) << std::endl;exit(1);}// CREATSHM 表示用 key 值创建共享内存,GETSHM 表示通过 key 值获取共享内存_shmid = shmget(key, size, flag | mode);if (_shmid < 0){std::cout << "共享内存创建失败: " << errno << " " << strerror(errno) << std::endl;exit(2);}// 关联_shmaddr = static_cast<char*>(shmat(_shmid, nullptr, 0));if (_shmaddr == (char*)-1){std::cout << "共享内存关联失败: " << errno << " " << strerror(errno) << std::endl;exit(3);}}SharedMemory(const SharedMemory& shm) = delete;SharedMemory& operator=(const SharedMemory& shm) = delete;~SharedMemory(){// 去关联shmdt(_shmaddr);// 销毁if (_type == CREAT) shmctl(_shmid, IPC_RMID, nullptr);}char* getAddr() { return _shmaddr; }private:int _type;int _shmid;char* _shmaddr;};
}#endif// server.cc
#include "shm.hpp"
#include <iostream>
#include <unistd.h>using namespace std;int main()
{starrycat::SharedMemory shm(CREATSHM, 0666);char* start = shm.getAddr();// 通信for (int i = 0; i < 5; ++i){cout << "从共享内存中读取: " << start << endl;sleep(1);}return 0;
}// client.cc
#include "shm.hpp"
#include <iostream>
#include <unistd.h>using namespace std;int main()
{starrycat::SharedMemory shm(GETSHM, 0666);char* start = shm.getAddr();// 通信for (int i = 0; i < 3; ++i){start[i] = 'A' + i;sleep(1);}return 0;
}

先启动 myserver,在启动 myclient

在这里插入图片描述

  • ipcs -m
    功能:查看共享内存
  • ipcmk -M 大小 -p 权限
    功能:创建共享内存
  • ipcrm -M/-m key/shmid
    功能:通过 key / shmid 删除共享内存

在这里插入图片描述

共享内存映射到进程的虚拟地址后,进程不需要通过系统调用来读取或写入数据,因此共享内存是所有进程间通信中速度最快的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/91002.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Python+OpenCV智能答题卡识别系统——深度学习和图像识别算法应用(含Python全部工程源码)+训练与测试数据集

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境PyCharm安装OpenCV环境 模块实现1. 信息识别2. Excel导出模块3. 图形用户界面模块4. 手写识别模块 系统测试1. 系统识别准确率2. 系统识别应用 工程源代码下载其它资料下载 前言 本项目基于Python和OpenCV图像处…

[maven]关于pom文件中的<relativePath>标签

关于pom文件中的<relativePath>标签 为什么子工程要使用relativePath准确的找到父工程pom.xml.因为本质继承就是pom的继承。父工程pom文件被子工程复用了标签。&#xff08;可以说只要我在父工程定义了标签&#xff0c;子工程就可以没有&#xff0c;因为他继承过来了&…

微信开发之一键踢出群聊的技术实现

简要描述&#xff1a; 删除群成员 请求URL&#xff1a; http://域名地址/deleteChatRoomMember 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选…

MySQL的字符转义

表象 表结构如下: 其中 content 字段存放json之后的数据,这个json数据里面 extra 字段的内容又是一段json,如下: INSERT INTO future.test_escape_character( id, title, content, is_del )VALUES ( 2, 我的博客, {"web_id":31415,"name":"清澄秋…

云计算中的负载均衡技术,确保资源的平衡分配

文章目录 1. 硬件负载均衡器2. 软件负载均衡器3. DNS负载均衡4. 内容分发网络&#xff08;CDN&#xff09; &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;云计算 ✨文章内…

CA证书颁发机构服务器

目录 一、CA证书颁发机构是什么&#xff1f; 二、数字证书可以干什么&#xff1f; 三、PKI&#xff1a;即公钥加密体系&#xff08;public key cryptography&#xff09; 四、CA在网络中的工作流程及原理&#xff08;以网站为例&#xff09; 五、HTTPS 的工作原理 六、CA私有证…

uview ui 1.x ActonSheet项太多,设置滚动(亲测有效)

问题&#xff1a;ActionSheet滚动不了。 使用uview ui &#xff1a;u-action-sheet, 但是item太多&#xff0c;超出屏幕了&#xff0c; 查了一下文档&#xff0c;并没有设置滚动的地方。 官方文档&#xff1a;ActionSheet 操作菜单 | uView - 多平台快速开发的UI框架 - uni-a…

数据时代的必备利器:数据可视化工具的崭新价值

在当今信息时代&#xff0c;数据扮演着越来越重要的角色&#xff0c;而数据的可视化呈现正是一种强大的工具&#xff0c;能够帮助我们更好地理解和利用这些数据。虽然Excel和PPT在处理数据方面有着不可否认的作用&#xff0c;但在处理大规模、复杂数据时&#xff0c;数据可视化…

RabbitMQ工作模式-工作队列

官网关于工作模式的解释地址&#xff1a;https://www.rabbitmq.com/getstarted.html Work Queue&#xff08;工作队列&#xff09; 生产者发消息&#xff0c;启动多个消费者来消费消息&#xff0c;每个消费者仅消费部分消息&#xff0c;可达到负载均衡的效果。 创建生产者 i…

【核磁共振成像】部分傅里叶重建

目录 一、部分傅里叶重建二、部分傅里叶重建算法2.1 填零2.2 零差处理 一、部分傅里叶重建 在部分傅里叶采集中&#xff0c;数据并不是绕K空间中心对称收集的&#xff0c;而是K空间的一半是完全填充的&#xff0c;另一半只收集了一小部分数据。   部分傅里叶采集所依据的原理…

【数据结构】C语言队列(详解)

前言: &#x1f4a5;&#x1f388;个人主页:​​​​​​Dream_Chaser&#xff5e; &#x1f388;&#x1f4a5; ✨✨专栏:http://t.csdn.cn/oXkBa ⛳⛳本篇内容:c语言数据结构--C语言实现队列 目录 一.队列概念及结构 1.1队列的概念 1.2队列的结构 二.队列的实现 2.1头文…

frida动态调试入门01——定位关键代码

说明 frida是一款Python工具可以方便对内存进行hook修改代码逻辑在移动端安全和逆向过程中常用到。 实战 嘟嘟牛登录页面hook 使用到的工具 1&#xff0c;jadx-gui 2&#xff0c;frida 定位关键代码 使用jadx-gui 进行模糊搜索&#xff0c;例如搜索encyrpt之类的加密关键…