【并发编程五】c++进程通信——共享内存(shared memmory)

news2024/11/23 18:35:32

【并发编程四】c++进程通信——共享内存(shared memmory)

  • 一、共享内存(shared memmory)
  • 二、共享内存的过程
    • 1、processA 写入共享内存
    • 2、processB 读取共享内存
  • 三、代码demo
    • 1、processA demo
    • 2、processB demo
  • 四、输出
  • 五 、共享内存的问题

在这里插入图片描述

一、共享内存(shared memmory)

消息队列的读取和写⼊的过程,都会有发⽣⽤户态与内核态之间的消息拷⻉过程。那共享内存的⽅式,就很好的解决了这⼀问题。

现代操作系统,对于内存管理,采⽤的是虚拟内存技术,也就是每个进程都有⾃⼰独⽴的虚拟内存空间,不同进程的虚拟内存映射到不同的物理内存中。所以,即使进程 A中 和 进程 B中 的虚拟地址是⼀样的,其实访问的是不同的物理内存地址,对于数据的增删查改互不影响。

共享内存的机制,就是拿出⼀块虚拟地址空间来,映射到相同的物理内存中。这样这个进程写⼊的东⻄,另外⼀个进程⻢上就能看到了,都不需要拷⻉来拷⻉去,传来传去,⼤⼤提⾼了进程间通信的速度。

二、共享内存的过程

在这里插入图片描述

我们以进程processA写,processB写为例,讲述下共享内存的过程

1、processA 写入共享内存

  • CreateFileMapping: 创建命名的内存映射文件对象 , Windows 即在物理内存申请一块指定大小的内存区域 , 返回文件映射对象的句柄 hMap ;
  • MapViewOfFile:为了能够访问这块内存区域 , 促使 Windows 将此内存空间映射到进程的地址空间中;
  • 通过句柄,把信息写入共享内存。

2、processB 读取共享内存

  • OpenFileMapping:打开共享内存。当在进程processB访问processA创建的内存区域时 , 则必须使用 OpenFileMapping 函数取得对象句柄hMap ,
  • MapViewOfFile:得到此内存空间的一个映射 , 这样系统就把同一块内存区域映射到了本进程的地址空间中 ,
  • 通过句柄,把共享内存信息的拷贝到进程的变量内。(其实,通过句柄,你已经可以看到共享内存的数据了,是否拷贝,是业务逻辑的事情)

这样就达到了共享内存的目的。

三、代码demo

1、processA demo

  • 只要不关闭共享内存的句柄,此创建共享内存的进程还在,其他进程就可以读取共享内存。
// main.cpp
#include <windows.h>
#include <iostream> 
using namespace std;

#define BUF_SIZE 4096

int main(int argc, TCHAR* argv[])
{
    // 定义共享数据
    char szBuffer[] = "Hello Shared Memory";

    // 创建共享文件句柄 
    HANDLE hMapFile = CreateFileMapping(
        INVALID_HANDLE_VALUE,   // 物理文件句柄
        NULL,                   // 默认安全级别
        PAGE_READWRITE,         // 可读可写
        0,                      // 高位文件大小
        BUF_SIZE,               // 地位文件大小
        "ShareMemory"           // 共享内存名称
    );

    // 映射缓存区视图 , 得到指向共享内存的指针
    LPVOID lpBase = MapViewOfFile(
        hMapFile,               // 共享内存的句柄
        FILE_MAP_ALL_ACCESS,    // 可读写许可
        0,
        0,
        BUF_SIZE
    );

    // 将数据拷贝到共享内存
    strcpy((char*)lpBase, szBuffer);
    cout << "存放入共享内存的数据:" << (char*)lpBase << endl;

    // 解除文件映射
    UnmapViewOfFile(lpBase);
    
    system("pause"); //等待其他进程读取数据

    // 关闭内存映射文件对象句柄,只要不关闭共享内存的句柄,此进程还在,其他进程就可以读取共享内存。
    //CloseHandle(hMapFile);
    return 0;
}

CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)

PROJECT(process)

ADD_EXECUTABLE(processA main.cpp)

ADD_SUBDIRECTORY(processB)

SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

2、processB demo

#include <iostream>  
#include <windows.h>  
using namespace std;

#define BUF_SIZE 4096

int main()
{
    cout << "processB" << endl << endl;

    // 打开共享的文件对象
    HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, NULL, "ShareMemory");
    if (hMapFile)
    {
        LPVOID lpBase = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
        // 将共享内存数据拷贝出来
        char szBuffer[BUF_SIZE] = { 0 };
        strcpy(szBuffer, (char*)lpBase);
        cout << "读取共享内存数据:" << szBuffer << endl;

        // 解除文件映射
        UnmapViewOfFile(lpBase);
        // 关闭内存映射文件对象句柄
        CloseHandle(hMapFile);
    }
    else
    {
        // 打开共享内存句柄失败
        cout << "Open Mapping Error";
    }
    system("pause");
    return 0;
}

CMAKE_MINIMUM_REQUIRED(VERSION 3.8.0)

SET(TARGET "childprocess")

ADD_EXECUTABLE(processB main.cpp)

SET(LIBRARY_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")
SET(EXECUTABLE_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/lib")

四、输出

因为之前的文章都有使用cmake编译的指令,后面就不再单独介绍了。
cmake -B build
cmake --build build

输出

在这里插入图片描述

五 、共享内存的问题

⽤了共享内存通信⽅式,带来新的问题,那就是如果多个进程同时修改同⼀个共享内存,很有可能就冲突了。例如两个进程都同时写⼀个地址,那先写的那个进程会发现内容被别⼈覆盖了。
为了防⽌多进程竞争共享资源,⽽造成的数据错乱,所以需要保护机制,使得共享的资源,在任意时刻只
能被⼀个进程访问。正好,信号量就实现了这⼀保护机制。
下一篇介绍信号量。

参考:
1、图解操作系统。
2、Windows上C++使用共享内存进行进程间通讯

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

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

相关文章

数学建模-基于LightGBM和BP神经网络的互联网招聘需求分析与预测

基于LightGBM和BP神经网络的互联网招聘需求分析与预测 整体求解过程概述(摘要) 就业是民生之本&#xff0c;是发展之基&#xff0c;也是安国之策。2020 年新冠肺炎疫情的爆发&#xff0c;稳就业成为应对疫情、稳定社会的重要保障之一。随着数据新动能的发展&#xff0c;互联网…

2023年全国硕士研究生入学统一考试管理类专业学位联考数学试题——解析版

文章目录 一、问题求解&#xff1a;真题&#xff08;2023-01&#xff09;-应用题-比例真题&#xff08;2023-02&#xff09;-应用题-利润真题&#xff08;2023-03&#xff09;-算术-分式真题&#xff08;2023-04&#xff09;-算术-有无理数真题&#xff08;2023-05&#xff09;…

let const 与var的区别

1、let可以形成块级作用域&#xff0c;在es6之前javascript只有函数作用域&#xff0c;没有块级作用域。在es6之前实现块级作用域: 2、可以看到通过一个立即执行函数表达式&#xff0c;我们实现了一个局部作用域或者块级作用域&#xff0c;但是有了let之后就不需要写这样的代…

从0开始学习JavaScript--JavaScript 箭头函数

JavaScript的现代语法&#xff0c;箭头函数&#xff08;Arrow Functions&#xff09;是一个不可忽视的重要部分。它们不仅提供了更简洁的语法&#xff0c;还改变了函数的作用域规则。在这篇文章中&#xff0c;将深入研究JavaScript箭头函数的概念、语法、用法以及它们与传统函数…

source: command not found错误的解决方法

偶遇的一个问题&#xff0c;因为在网上没有找到对应的解决办法&#xff0c;可能是属于个案&#xff0c;在此记录备忘&#xff0c;同时供大家参考。 问题现象&#xff1a; 执行命令 source /etc/profile时报错&#xff1a; bash: “source: command not found... 问题定位和…

电子签名软件,在教育行业中如何应用?

电子签名软件简化签署流程&#xff0c;降低签署门槛&#xff0c;让更多人便捷地参与到签署中来。 微签作为国内电子签名软件的拓荒者之一&#xff0c;拥有19年的研发应用经验&#xff0c;提供专业的企业电子签名服务。微签的电子签名软件广泛应用于审批场景&#xff0c;实现高…

Dropdown下拉菜单(antd-design组件库)简单用法和禁用菜单

1.Dropdown下拉菜单 向下弹出的列表。 2.何时使用 当页面上的操作命令过多时&#xff0c;用此组件可以收纳操作元素。点击或移入触点&#xff0c;会出现一个下拉菜单。可在列表中进行选择&#xff0c;并执行相应的命令。 用于收罗一组命令操作。 Select 用于选择&#xff0c;而…

C++: String类接口学习

文章目录 STL简介一. 为什么要有string类二. STL 中的 string 类介绍1. string 类描述2. 关于 basic_string 三. string 类的常用接口1. string 类的常见构造2. string 类的容量操作size 和 lengthcapacitymax_sizereserveresize 3. string 类对象的访问及遍历操作operator[] 和…

酷开系统 | 酷开科技聚焦价值人群 助力营销增长

2023年&#xff0c;是消费复苏回暖的一年&#xff0c;市场中充溢着大量品牌重启增长的机遇与实例。品牌商期望能够把握住市场趋势&#xff0c;通过营销获得确定性的业绩提升&#xff0c;并在未来收获长期稳定的增长。作为数字媒介的代表之一&#xff0c;OTT大屏营销的属性和价值…

深入浅出 Vue 中的插槽 slot

深入浅出 Vue 中的插槽 slot start 最近被问到好几次 Vue 中的插槽相关知识&#xff0c;掌握的还是有些不全面。抱着重新学习的心态&#xff0c;写这篇博客。首先对基础知识做一个回顾&#xff0c;然后再对源码实现做一个学习。作者&#xff1a;番茄编写时间&#xff1a;2023…

泄密零容忍!迅软科技打造设计图纸安全防线,助您无忧创作!

对于建筑设计、鞋服设计、动漫设计、平面设计等设计行业而言&#xff0c;海量设计图纸都以电子数据的形式存在企业的终端电脑上&#xff0c;这些图纸蕴含着企业的核心竞争资源&#xff0c;一旦泄露将给企业带来巨大的经济损失。 因此&#xff0c;迅软科技采用了先进的数据加密技…

自写一个函数将js对象转为Ts的Interface接口

如今的前端开发typescript 已经成为一项必不可以少的技能了&#xff0c;但是频繁的定义Interface接口会给我带来许多工作量&#xff0c;我想了想如何来减少这些非必要且费时的工作量呢&#xff0c;于是决定写一个函数&#xff0c;将对象放进它自动帮我们转换成Interface接口&am…

嵌入式总线技术详解

1. 总线概述 1.1 总线定义 总线&#xff08;Bus&#xff09;是计算机各种功能部件之间传送信息的公共通信干线它是由导线组成的传输线束&#xff0c;按照计算机所传输的信息种类&#xff0c;计算机的总线可以划分为数据总线、地址总线和控制总线&#xff0c;分别用来传输数据…

20天GMV超过百万美金!桌下迷你跑步机在TikTok Shop美国站热销

上周总GMV达到1.59亿美元&#xff0c;达到历史新高&#xff0c;是美国站自开通以来首次单周出单达到亿级&#xff1b;日均出单1660万美元&#xff0c;单日出单最高达2820万美元&#xff1b; 截至11月19日&#xff0c;GMV Top 5 的商品分类排名依次为&#xff1a;美妆个护、女士…

【vue脚手架配置代理+github用户搜索案例+vue项目中常用的发送Ajax请求的库+slot插槽】

vue脚手架配置代理github用户搜索案例vue项目中常用的发送Ajax请求的库slot插槽 1 vue脚手架配置代理2 github用户搜索案例2.1 静态列表2.2 列表展示2.3 完善案例 3 vue项目中常用的发送Ajax请求的库3.1 xhr3.2 jQuery3.3 axios3.4 fetch3.5 vue-resource 4 slot 插槽4.1 效果4…

【嵌入式】开源shell命令行的移植和使用(1)——nr_micro_shell

目录 一 背景说明 二 移植准备 三 移植过程 四 实际使用 一 背景说明 在进行调试和维护时&#xff0c;常常需要与单片机进行交互&#xff0c;获取、设置某些参数或执行某些操作&#xff0c;nr_micro_shell正是为满足这一需求&#xff0c;针对资源较少的MCU编写的基本命令行…

VT-MRPA1-151-1X/V0/0控制2FRE16模块式模拟放大器

适用于控制带有电气位置反馈的直动式比例减压阀&#xff08;DBETR- 1X 类型&#xff09;或带有电气位置反馈的比例流量控制阀&#xff08;2FRE... 类型&#xff09;&#xff1b;控制值输入 1 0 V&#xff08;差动输入&#xff09;&#xff1b; 可分别调节“上/下”斜坡时间的斜…

计算机网络:快速了解网络框架

文章目录 前言一、什么是Internet&#xff1f;1.从具体构成角度什么是协议&#xff1f; 2.从服务角度3小结 二、网络边缘1.采用网络设施面向连接服务&#xff08;TCP&#xff09;2.采用基础设施的无连接服务&#xff08;UDP&#xff09; 三、网络的核心1.电路交换2.分组交换3.分…

vue2 el-table 封装

vue2 el-table 封装 在 custom 文件夹下面创建 tableList.vue直接上代码&#xff08;代码比较多&#xff0c;复制可直接用&#xff09; <template><div class"mp-list"><el-tableref"multipleTable"class"mp-custom-table":dat…

一起学docker系列之十二什么是dockerfile

目录 1 基本概念2 语法规则3 Dockerfile构建步骤4 Dockerfile、Docker镜像和Docker容器的关系5 保留字介绍5.1 FROM5.2 MAINTAINER5.3 RUN5.4 EXPOSE5.5 WORKDIR5.6 USER5.7 ENV5.8 ADD5.9 COPY5.10 VOLUME5.11 CMD5.12 ENTRYPOINT 6 总结7 参考地址 1 基本概念 Dockerfile是一…