【进程间通信】共享内存

文章目录

  • 共享内存
    • 常用的接口
    • 指令
    • 利用命名管道实现同步机制
    • 总结

System V的IPC资源的生命周期都是随内核的。

共享内存

共享内存也是为了进程间进行通信的,因为进程间具有独立性,通信的本质是两个不同的进程看到同一份公共资源,所以共享内存一定是由OS提供的,共享内存的本质就是,在内存中开辟一块空间,然后映射在需要通过这片空间的进程的地空间中堆和栈之间共享区,通过这样的方式让两个不同的进程看到同一份公共资源。如下图:
在这里插入图片描述
一个共享内存可以满足很多进程进行通信,它可以挂载很多进程,但是OS中的进程是很多的,不同的进程和不同的进程之间需要通信的内容和方式也不太一样,所以OS中一定会存在大量的共享内存,因此OS一定要对共享内存进行管理(先描述,在组织),所以OS中一定有描述共享内存的各种属性的结构体,然后用链表等数据结构把OS中存在的共享内存管理起来,这样对共享内存的管理就变成了对链表的增删查改。
在这里插入图片描述

那么如何保证两个不同进程能看到同一个共享内存呢?
OS是让两个进程通过约定的方式让不同的进程看到同一块共享内存,两个进程约定一个key值,这个key值会被写入shm结构体中,然后不同的进程拿着相同的key值,就可以看到同一份共享内存了,但是系统中的共享内存会存在很多个,这个key值每个共享内存应该是不同的,所以我们需要尽可能的保证key的唯一性,但是让用户来进行这个操作,明显是不靠谱的,所以有个系统调用的函数,可以来帮助我们形成这个key值。
在这里插入图片描述
只需要传进去一个字符串和一个整型变量,这个函数就会通过自身的算法给我们形成一个key值,两个不同的进程拿着相同的字符串和相同的整型变量再通过相同的算法,形成的key值一定是一样的。这个key值最终是要被写进内核数据结构的。
在这里插入图片描述
这个__key就是我们用户自己传进去的key。共享内存 = 共享内存空间 + 共享内存属性

常用的接口

shmget
在这里插入图片描述
第一个参数就是我们之前自己形成的key,最后一个最常用的标志位就两个,IPC_CREAT和IPC_EXCL

  1. IPC_CREAT :不存在就创建,存在就获取
  2. IPC_EXCL:单独使用没有任何意义,和IPC_CREAT 一起使用,不存在就创建,存在就报错,这两个参数一起使用可以保证一定是第一次创建共享内存。

第三个参数的标志位后面可以直接跟共享内存的权限,具体可以参考下面的代码。

它的返回值就类似于文件描述符,方便用户操作,并且后面的节后都需要用这个shmid来标识自己创建的共享内存,我们的key是内核里面用的为了标识共享内存的唯一性,我们用户用的都是shmid,并且指令删除共享内存也是要用shmid不能使用key。

shmat
在这里插入图片描述
在这里插入图片描述

创建成功后,我们会拿到一个指针,这个指针就和malloc开辟的空间一样,可以直接拿着指针对这块内存进行操作。第二个参数我们一般为nullptr就行,最后一个参数一般为0。

shmdt
在这里插入图片描述

shmctl
在这里插入图片描述
在这里插入图片描述

指令

常用相关的函数就是这些,在Linux中如果我们要查看已经创建的共享内存有哪些,可以使用ipcs -m 指令
在这里插入图片描述
想要删除一个共享内存可以使用ipcrm -m shmid 的方式删除
在这里插入图片描述
最后的数字应该为具体的shmid。

利用命名管道实现同步机制

共享内存不会提供同步机制,但是他是需要同步机制的,我们可以使用管道来实现它的同步机制,接下来我们可以利用前面的命名管道尝试实现一下这个同步机制。

我们需要两个独立的进程一个server,一个client,所以我们需要一个可以形成两个可执行程序的Makefile。

.PHONY:all
all:client serverclient:Client.ccg++ -o $@ $^ -std=c++11server:Server.ccg++ -o $@ $^ -std=c++11.PHONY:clean
clean:rm -rf client server

然后我们需要一个Client.cc和Server.cc,但是我们需要形成同一个key,所以我们可以把两个源文件中需要两个进程看到的同一份资源抽出来,Com.hpp。

Com.hpp

#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>const std::string path = "/home/ysl/long/class_dragon/test_5_8/shm";
const std::string filename = "fifo";
const int proj_id = 0x11223344;
const int num = 4096;key_t getkey()
{key_t key = ftok(path.c_str(), proj_id);if(key < 0){std::cerr << "getkey error" << std::endl;exit(-1);}return key;
}int _getshm(key_t key, int flag)
{int shmid = shmget(key,num,flag);if(shmid < 0){std::cerr << "shm error" << std::endl;exit(-1);}return shmid;
}   int Create_shm(key_t key)
{return _getshm(key,IPC_CREAT|IPC_EXCL|0644);
}int getshm(key_t key)
{return _getshm(key,IPC_CREAT);
}bool Create_fifo()
{int n = mkfifo(filename.c_str(),0666);if(n < 0){std::cerr << "mkfifo error" << std::endl;return false;}return true;
}

Server.cc

#include "Com.hpp"class Init
{
public:Init(){//创建命名管道Create_fifo();// 获取keykey_t key = getkey();// 创建共享内存shmid = Create_shm(key);std::cout << shmid << std::endl;std::cout << "chuangjian" << std::endl;// 挂载addr = (char *)shmat(shmid, nullptr, 0);std::cout << "guazai" << errno << std::endl;fd = open(filename.c_str(),O_RDONLY);}~Init(){shmdt(addr);std::cout << "qu" << std::endl;// 删除共享内存shmctl(shmid, IPC_RMID, nullptr);std::cout << "shan" << std::endl;close(fd);unlink(filename.c_str());}public:int shmid;char *addr;int fd;
};Init init;
int main()
{while(true){int code = 0;ssize_t n = read(init.fd,&code,sizeof code);if(n > 0){std::cout << init.addr << std::endl;}else if(n == 0){break;}//sleep(1);}return 0;
}

Client.cc

#include "Com.hpp"class Init
{
public:Init(){// 获取keykey_t key = getkey();// 创建共享内存shmid = getshm(key);// 挂载addr = (char *)shmat(shmid, nullptr, 0);}~Init(){shmdt(addr);}public:int shmid;char *addr;
};Init init;int main()
{int fd = open(filename.c_str(),O_WRONLY);for(char ch = 'a'; ch <= 'z'; ++ch){int code = 1;write(fd,&code,sizeof code);init.addr[ch-'a'] = ch;sleep(1);}return 0;
}

我们是可以通过命名管道让共享内存拥有同步机制的。

总结

  1. 共享内存的通信方式,不会提供同步机制,共享内存是直接裸露给所有的使用者的,所以一定要注意共享内存的使用安全问题。
  2. 共享内存可以提供较大的空间。
  3. 共享内存是所有进程间通信中速度最快的。可以减少数据拷贝的次数。

为什么说共享内存是最快的?
这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据,也就会减少很多的数据的拷贝。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

软件库1.3版本更新-iApp源码

更新内容 1、对首页.iyu&#xff0c;软件按钮.iyu&#xff0c;主页.iyu&#xff0c;软件详情.iyu&#xff0c;搜索引擎.iyu进行了部分美化和优化 2、首页.iyu已经新增下拉刷新功能 3、新增下载管理模块&#xff08;下载管理.iyu&#xff0c;下载管理按钮.iyu&#xff0c;我的…

网站localhost和127.0.0.1可以访问,本地ip不可访问解决方案

部署了一个网站, 使用localhost和127.0.0.1加端口号可以访问, 但是使用本机的ip地址加端口号却不行. 原因可能有多种. 可能的原因: 1 首先要确认是否localhost对应的端口是通的(直接网址访问), 以及你无法访问的那个本机ip是否正确(使用ping测试)&#xff1b; 2 检查本机的防火…

短视频矩阵系统源码/saas--总后台端、商户端、代理端、源头开发

短视频矩阵系统源码/saas--总后台端、商户端、代理端、源头开发 搭建短视频矩阵系统源码的交付步骤可以概括为以下几个关键环节&#xff1a; 1. **系统需求分析**&#xff1a;明确系统需要支持的功能&#xff0c;如短视频的上传、存储、播放、分享、评论、点赞等。 2. **技术选…

从零开始学C语言系列之第五章《for开篇》

往期回顾 1.【第一章】《认识C语言》 2.【第二章】C语言概述及基本知识1 3.【第二章】C语言概述及基本知识2 4.【第三章】字符串和格式化输入/ 输出 5.【第三章】 printf 6.【第三章】 scanf 7.【第三章】 putchar 8.【第三章】 getchar 9.【第三章】 sizeof 10.【第三章】 st…

数据库数据恢复—Sql Server数据库文件丢失丢失怎么恢复数据?

数据库数据恢复环境&#xff1a; 5块硬盘组建一组RAID5阵列&#xff0c;划分LUN供windows系统服务器使用。windows系统服务器内运行了Sql Server数据库&#xff0c;存储空间在操作系统层面划分了三个逻辑分区。 数据库故障&#xff1a; 数据库文件丢失&#xff0c;主要涉及3个…

UA身份伪装

import urllib.requesturl https://www.baidu.com/# 指定自定义请求头 headers {User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.95 Safari/537.36 }# 创建带有自定义请求头的请求对象 custom_request …

ChatPPT开启高效办公新时代,AI赋能PPT创作

目录 一、前言二、ChatPPT的几种用法1、通过在线生成2、通过插件生成演讲者模式最终成品遇到问题改进建议 三、ChatPPT其他功能 一、前言 想想以前啊&#xff0c;为了做个PPT&#xff0c;我得去网上找各种模板&#xff0c;有时候还得在某宝上花钱买。结果一做PPT&#xff0c;经…

【Linux】Linux——Centos7安装RabbitMQ

目录 安装包准备socaterlang 安装rabbitmq安装命令启动rabbitmq&#xff0c;两种方式查看rabbitmq 启动后的情况配置并开启网页插件关闭防火墙或开放端口测试登录问题配置web端访问账号密码和权限添加用户&#xff0c;后面两个参数分别是用户名和密码.添加权限修改用户角色再次…

信息系统项目管理师0095:项目管理知识领域(6项目管理概论—6.4价值驱动的项目管理知识体系—6.4.4项目管理知识领域)

点击查看专栏目录 文章目录 6.4.4项目管理知识领域6.4.4项目管理知识领域 除了过程组,过程还可以按知识领域进行分类。知识领域指按所需知识内容来定义的项目管理领域,并用其所含过程、实践、输入、输出、工具和技术进行描述。 虽然知识领域相互联系,但从项目管理的角度来看…

Unity如何使用adb工具安装APK

1、下载adb工具 SDK 平台工具版本说明 | Android Studio | Android Developers (google.cn) 2、配置环境变量 把platform-tools的路径添加进去就行 打开cmd&#xff0c;输入adb&#xff0c;即可查看版本信息 3、使用数据线连接设备&#xff0c;查看设备信息&#xff08;…

网络层协议之 IP 协议

IP 协议格式 4 位版本&#xff1a;此处的取值只有两个&#xff0c;4&#xff08;IPv4&#xff09;和 6&#xff08;IPv6&#xff09;&#xff0c;即指定 IP 协议的版本。 4 位首部长度&#xff1a;描述了 IP 报头多长&#xff0c;IP 报头是变长的&#xff0c;因为报头中的选项部…

WPF/C#:ProgressBar的基本使用

前言 在日常开发过程中&#xff0c;如果遇到需要一段时间才能完成的任务&#xff0c;通常需要给用户一个进度条提示。今天给大家介绍的是WPF/C#中ProgressBar的基本使用。 ProgressBar的介绍 在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;Pr…

【c++】继承学习(三)菱形继承的挑战与虚拟继承的策略

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章来讲解继承的第三部分&#xff0c;有关多继承和菱形继承的内容 目录 1.菱形继承2.虚拟继承3.虚拟继承解决数据冗余和二义性的原理4.继承的总结和反思继承…

团结引擎+OpenHarmony 3 通信

团结引擎和鸿蒙之间通信 因为 ts 并没有像 JAVA 有反射的调用&#xff0c;所以我们必须要像 Web GL 平台一样通过导出的行为告诉引擎到底哪些 ts 的接口可以给 C# 来调用。 1 在 Tuanjie 引擎里 需要一个tsllib文件&#xff0c;用于设置给导出对象 C#使用。就可以直接创建以 …

回答篇:测试开发高频面试题目

引用之前文章&#xff1a;《测试开发高频面试题目》 https://blog.csdn.net/qq_41214208/article/details/138193469?spm1001.2014.3001.5502 本篇文章是回答篇&#xff08;持续更新中&#xff09; 1. 什么是测试开发以及其在软件开发流程中的作用。 a. 测试开发是指测试人员或…

MyBatis认识

一、定义 MyBatis是一款优秀的持久层框架&#xff0c;它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO&#xff08;Plain Old Java O…

无人机+通信中继:短波电台技术详解

随着无线通信技术的不断发展&#xff0c;无人机作为一种新型的信息传输平台&#xff0c;已经在多个领域得到了广泛应用。其中&#xff0c;无人机与短波电台的结合&#xff0c;为通信中继领域带来了全新的可能性。本文将详细解析无人机在通信中继中的应用&#xff0c;以及短波电…

十二届蓝桥杯Python组1月中/高级试题 第一题

** 十二届蓝桥杯Python组1月中/高级试题 第一题 第一题&#xff08;难度系数2&#xff0c;18 个计分点&#xff09; 编程实现&#xff1a; 输入一个字符串&#xff0c;输出这个字符串的最后一个字符。 输入描述&#xff1a;输入一个字符串 输出描述&#xff1a;输出这个字符串…

Electron项目中将CommonJS改成使用ES 模块(ESM)语法preload.js加载报错

问题 将Electron项目原CommonJS语法改成使用ES 模块&#xff08;ESM&#xff09;语法&#xff0c;preload.js一直加载不到&#xff0c;报错如下&#xff1a; VM111 renderer_init:2 Unable to load preload script: D:\Vue\wnpm\electron\preload.js VM111 renderer_init:2 E…

Hive SQL-DQL-Select查询语句用法详解

HQL Select用法详解 1.基础语法 &#xff08;1&#xff09;select_exp &#xff08;2&#xff09;ALL、DISTINCT &#xff08;3&#xff09;WHERE &#xff08;4&#xff09;分区查询、分区裁剪 &#xff08;5&#xff09;GROUP BY &#xff08;6&#xff09;HAVING &#xff0…