C#与C++交互开发系列(二十):跨进程通信之共享内存(Shared Memory)

在这里插入图片描述

1、前言

共享内存(Shared Memory)是一种高效的跨进程通信方式,尤其适用于同一台计算机上的进程之间的高速数据传输。与套接字相比,共享内存允许多个进程直接访问同一块内存区域,减少了数据传输的中间步骤,适合需要高性能和低延迟的场景。本文将介绍如何在 C# 和 C++ 之间通过共享内存实现跨进程通信,并附上完整的示例代码。

2、什么是共享内存?

共享内存是一种在操作系统中分配的内存区域,允许多个进程对该内存区域进行读写。不同于管道或套接字,数据不需要被复制到缓冲区中进行传输,而是直接由各个进程访问内存数据,从而提高了数据传输效率。

3、实现步骤

  1. C++ 进程:创建共享内存区域,将数据写入内存。
  2. C# 进程:打开该共享内存区域,从内存中读取数据。

4、示例代码

以下代码展示了一个 C++ 进程创建并写入共享内存,另一个 C# 进程读取该共享内存中的数据。

C++ 代码:创建并写入共享内存

使用 Windows API 创建共享内存,并将数据写入共享内存区域。

#include <windows.h>
#include <iostream>
#include <cstring>int main() {const char* sharedMemoryName = "Local\\MySharedMemory";const char* message = "Hello from C++!";// 创建共享内存HANDLE hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,256,sharedMemoryName);if (hMapFile == NULL) {std::cerr << "Could not create file mapping object: " << GetLastError() << std::endl;return 1;}// 映射内存LPVOID pBuf = MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,0,0,256);if (pBuf == NULL) {std::cerr << "Could not map view of file: " << GetLastError() << std::endl;CloseHandle(hMapFile);return 1;}// 写入数据到共享内存CopyMemory((PVOID)pBuf, message, strlen(message) + 1);std::cout << "Data written to shared memory: " << message << std::endl;std::cout << "Press Enter to exit...";std::cin.get();// 释放资源UnmapViewOfFile(pBuf);CloseHandle(hMapFile);return 0;
}

代码解析

  • CreateFileMappingA:创建共享内存对象。
  • MapViewOfFile:将共享内存映射到进程地址空间。
  • CopyMemory:将数据写入共享内存。
  • UnmapViewOfFileCloseHandle:释放内存映射并关闭句柄。

C# 代码:读取共享内存

在 C# 中使用 MemoryMappedFile 类打开并读取共享内存数据。

using System;
using System.IO.MemoryMappedFiles;
using System.Text;class Program {static void Main() {const string sharedMemoryName = "Local\\MySharedMemory";// 打开共享内存using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(sharedMemoryName)) {// 读取共享内存数据using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(0, 256)) {byte[] buffer = new byte[256];accessor.ReadArray(0, buffer, 0, buffer.Length);// 将字节数组转换为字符串string message = Encoding.ASCII.GetString(buffer).TrimEnd('\0');Console.WriteLine("Data read from shared memory: " + message);}}}
}

代码解析

  • MemoryMappedFile.OpenExisting:打开现有的共享内存对象。
  • MemoryMappedViewAccessor:创建内存视图以读取共享内存中的数据。
  • ReadArray:从共享内存中读取数据。
  • Encoding.ASCII.GetString:将字节数组转换为字符串。

5、运行步骤

  1. 编译并运行 C++ 程序,它将创建共享内存并写入数据。
  2. 运行 C# 程序,它将打开并读取共享内存中的数据。

运行结果:
在这里插入图片描述

  • C++ 程序输出:Data written to shared memory: Hello from C++!
  • C# 程序输出:Data read from shared memory: Hello from C++!

6、注意事项

  1. 命名空间一致性:确保共享内存名称一致,否则 C# 程序无法找到 C++ 程序创建的共享内存。
  2. 访问权限:共享内存的访问权限应当在 C++ 和 C# 之间保持一致。
  3. 数据格式:在多字节字符的处理上要确保编码一致,以免出现乱码。

7、应用场景

  • 高性能数据传输:适用于大数据量、低延迟的应用场景,如视频处理、游戏引擎等。
  • 跨进程数据共享:允许多个进程同时访问同一块数据,减少数据复制开销。

8、优缺点

  • 优点
    • 高速数据传输,适合大数据量传输场景。
    • 不需要数据序列化与反序列化,降低了性能开销。
  • 缺点
    • 只适用于同一台计算机上的进程通信。
    • 需要注意数据同步,避免多个进程同时写入导致的数据竞争。

9、总结

通过共享内存,C# 和 C++ 程序能够实现高效的跨进程通信,适用于高频、大数据量的数据传输需求。共享内存虽然具备较高的性能优势,但同时需要妥善管理访问权限和数据同步。

在下一篇文章中,我们将介绍 消息队列(Message Queues) 的实现方法,它更适合分布式系统中数据量不大但需要排队处理的场景。

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

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

相关文章

智慧公厕解决方案是未来厕所新建和改造的方向

在当今科技飞速发展的时代&#xff0c;智慧公厕解决方案正逐渐成为厕所新建和改造的主流方向&#xff0c;为人们带来更便捷、卫生、高效的使用体验。 一、智能化体验提升便捷性 智慧公厕配备了一系列智能设施&#xff0c;极大地提升了使用的便捷性。比如&#xff0c;智能环保取…

C++ | Leetcode C++题解之第542题01矩阵

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {int m matrix.size(), n matrix[0].size();// 初始化动态规划的数组&#xff0c;所有的距离值都设置为一个很大的…

Vue3中实现原生CSS完成圆形按钮点击粒子效果和定点旋转动画

效果&#xff1a; 源码&#xff1a; <script setup> import { ElMessage } from "element-plus"; const isClick () > {ElMessage.success(Clicked); }; </script><template><button click"isClick" class"button">…

DGL之copy_e和copy_u

消息函数copy_e和copy_u用法 copy_e语法格式例子 copy_u语法格式例子 copy_e 语法格式 dgl.function.copy_e(e, out)参数&#xff1a; e (str)&#xff1a;边的特征字段&#xff0c;指定用于计算消息的边特征。out (str)&#xff1a;输出的消息字段&#xff0c;指定存储消息…

python画图|hist()函数深层体验

【1】引言 前述学习已经掌握hist()函数的基本运用技巧&#xff0c;可通过下述链接直达&#xff1a; python画图|hist()函数画直方图初探-CSDN博客 python画图|hist()函数画直方图进阶-CSDN博客 我们已经理解hist()函数本质上画的是概率分布图&#xff0c;相关知识属于数理统…

黄山谷捷:以创新为翼,领航新能源汽车散热基板行业

在竞争激烈的市场环境中&#xff0c;创新被视为企业发展的灵魂和生命线&#xff0c;是推动持续成长、保持竞争力的关键要素。作为专注于功率半导体模块散热基板研发、生产和销售的高新技术企业&#xff0c;黄山谷捷股份有限公司具有优秀的创新文化和基因&#xff0c;为公司的高…

如何提升论文写作能力?

很多同学刚开始都不知道如何写作学术论文&#xff0c;这个也很正常&#xff0c;否则要导师来做什么。而且写作是需要练习的,等你写了5篇以上的论文&#xff0c;你就有感觉了。其次&#xff0c;你们感觉论文写作不知道从何下手还有个重要原因是缺少指导&#xff0c;最近接触了几…

梧桐数据库中的条件表达式灵活的数据选择与操作分享

在数据库操作中&#xff0c;条件表达式是处理数据选择和操作的强大工具。它们允许我们在单个查询中根据条件动态地返回不同的值。梧桐数据库支持多种条件表达式&#xff0c;包括CASE、COALESCE、NULLIF等&#xff0c;这些表达式在数据查询和处理中扮演着重要角色。本文将详细介…

配置管理,雪崩问题分析,sentinel的使用

目录 配置管理一&#xff1a;什么是配置管理二&#xff1a;配置共享三&#xff1a;配置热更新 雪崩问题一&#xff1a;原因分析二&#xff1a;解决方案 Sentinel一&#xff1a;快速入门二&#xff1a;请求限流三&#xff1a;线程隔离四&#xff1a;fallback五&#xff1a;服务熔…

算法练习:904. 水果成篮

题目链接&#xff1a;904. 水果成篮。 题目意思就是可以选取两个种类的水果不能超过两个种类&#xff0c;该种类个数没有限制&#xff0c; 但是一旦超过两个种类的水果就要停止计数。 示例中数组编号就是就是种类&#xff0c;就是不能出现三个不同编号的数。 1.暴力解法&…

邮件营销模板定制服务:满足个性营销需求!

邮件营销模板创建步骤&#xff1f;外贸营销邮件范文模板有哪些&#xff1f; 为了在众多邮件中脱颖而出&#xff0c;企业需要定制化的邮件营销模板&#xff0c;以更好地传达品牌信息&#xff0c;提升客户参与度。MailBing将探讨邮件营销模板定制服务的重要性&#xff0c;并介绍…

cuda 环境搭建

官网安装教程 https://docs.nvidia.com/deeplearning/cudnn/latest/installation/windows.html 1. 下载安装驱动&#xff0c; 安装完成之后输入 nvidia-smi 查看结果 https://www.nvidia.cn/drivers/lookup/ 2. 安装工具链 安装完成之后输入 nvcc -v 查看结果 http…

unity 镜面 反射

URP 镜面 资源绑定 下载 namespace UnityEngine.Rendering.Universal { [ExecuteInEditMode]public class PlanarURP : MonoBehaviour{public bool VR false;public int ReflectionTexResolution 512;public float Offset 0.0f;[Range(0, 1)]public float Reflecti…

细说STM32单片机USART中断收发RTC实时时间并改善其鲁棒性的另一种方法

目录 一、工程目的 1、目标 2、通讯协议及应对错误指令的处理目标 二、工程设置 三、程序改进 四、下载与调试 1、合规的指令 2、不以#开头&#xff0c;但以&#xff1b;结束&#xff0c;长度不限 3、以#开头&#xff0c;不以;结束&#xff0c;也不包含;&#xff0c;长…

leetcode 2043.简易银行系统

1.题目要求: 示例: 输入&#xff1a; ["Bank", "withdraw", "transfer", "deposit", "transfer", "withdraw"] [[[10, 100, 20, 50, 30]], [3, 10], [5, 1, 20], [5, 20], [3, 4, 15], [10, 50]] 输出&#xff…

JVM 复习1

内容 JVM 类加载器 JVM 运行时数据区 测试1 JVM整体架构考察。整体架构分为哪三层。分别是什么&#xff1f;通过绘制架构图来作答。 前端编译器是什么&#xff0c;作用是什么。要进行那些步骤&#xff1f; 类加载构成几个步骤。并且详细作答每个步骤的工作。 准备阶段和初…

Android——网络请求

get 请求 public static String doGeg() {String result "";BufferedReader reader;try {// 1.建立连接HttpURLConnection httpURLConnection null;String url "https://www.baidu.com";URL requestUrl new URL(url);httpURLConnection (HttpURLConn…

软件技术求职简历「优选篇」

【#软件技术简历#】一份精心撰写的简历是增加获得心仪职位的机会。那么&#xff0c;如何才能写出一份既全面又吸引人的软件技术简历呢&#xff1f;以下是幻主简历整理的软件技术简历「优选篇」&#xff0c;欢迎大家阅读收藏&#xff01; 软件技术简历范文&#xff1a; 求职意向…

GESP4级考试语法知识(算法概论(三))

爱因斯坦的阶梯代码&#xff1a; //算法1-12 #include<iostream> using namespace std; int main() {int n1; //n为所设的阶梯数while(!((n%21)&&(n%32)&&(n%54)&&(n%65)&&(n%70)))n; //判别是否满足一组同余式cout<<n<…

SOCKS5协议

SOCKS5协议连接过程 SOCKS5服务器默认监听的端口是1080端口 连接到服务器:SOCKS5客户端会通过TCP三次握手与SOCKS5服务器建立连接协商过程:首先SOCKS5客户端会发送一个请求到服务器。告诉服务器自己支持什么方法。并带有一个方法列表(例如&#xff1a;A,B,C)。然后SOCKS5服务…