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

[复制链接]
发表于 2025-12-30 03:35:17 | 显示全部楼层 |阅读模式

1、媒介

共享内存(Shared Memory)是一种高效的跨进程通讯方式,尤着实用于同一台盘算机上的进程之间的高速数据传输。与套接字相比,共享内存答应多个进程直接访问同一块内存地区,镌汰了数据传输的中心步调,得当须要高性能和低耽误的场景。本文将先容如安在 C# 和 C++ 之间通过共享内存实现跨进程通讯,并附上完备的示例代码
2、什么是共享内存?

共享内存是一种在使用体系中分配的内存地区,答应多个进程对该内存地区举行读写。差异于管道或套接字,数据不须要被复制到缓冲区中举行传输,而是直接由各个进程访问内存数据,从而进步了数据传输服从。
3、实现步调


  • C++ 进程:创建共享内存地区,将数据写入内存。
  • C# 进程:打开该共享内存地区,从内存中读取数据。
4、示例代码

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

使用 Windows API 创建共享内存,并将数据写入共享内存地区。
  1. #include <windows.h>
  2. #include <iostream>
  3. #include <cstring>
  4. int main() {
  5.     const char* sharedMemoryName = "Local\\MySharedMemory";
  6.     const char* message = "Hello from C++!";
  7.     // 创建共享内存
  8.     HANDLE hMapFile = CreateFileMappingA(
  9.         INVALID_HANDLE_VALUE,
  10.         NULL,
  11.         PAGE_READWRITE,
  12.         0,
  13.         256,
  14.         sharedMemoryName
  15.     );
  16.     if (hMapFile == NULL) {
  17.         std::cerr << "Could not create file mapping object: " << GetLastError() << std::endl;
  18.         return 1;
  19.     }
  20.     // 映射内存
  21.     LPVOID pBuf = MapViewOfFile(
  22.         hMapFile,
  23.         FILE_MAP_ALL_ACCESS,
  24.         0,
  25.         0,
  26.         256
  27.     );
  28.     if (pBuf == NULL) {
  29.         std::cerr << "Could not map view of file: " << GetLastError() << std::endl;
  30.         CloseHandle(hMapFile);
  31.         return 1;
  32.     }
  33.     // 写入数据到共享内存
  34.     CopyMemory((PVOID)pBuf, message, strlen(message) + 1);
  35.     std::cout << "Data written to shared memory: " << message << std::endl;
  36.     std::cout << "Press Enter to exit...";
  37.     std::cin.get();
  38.     // 释放资源
  39.     UnmapViewOfFile(pBuf);
  40.     CloseHandle(hMapFile);
  41.     return 0;
  42. }
复制代码
代码分析

  • CreateFileMappingA:创建共享内存对象。
  • MapViewOfFile:将共享内存映射到进程地点空间。
  • CopyMemory:将数据写入共享内存。
  • UnmapViewOfFile 和 CloseHandle:开释内存映射并关闭句柄。
C# 代码:读取共享内存

在 C# 中使用 MemoryMappedFile 类打开并读取共享内存数据。
  1. using System;
  2. using System.IO.MemoryMappedFiles;
  3. using System.Text;
  4. class Program {
  5.     static void Main() {
  6.         const string sharedMemoryName = "Local\\MySharedMemory";
  7.         // 打开共享内存
  8.         using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(sharedMemoryName)) {
  9.             // 读取共享内存数据
  10.             using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(0, 256)) {
  11.                 byte[] buffer = new byte[256];
  12.                 accessor.ReadArray(0, buffer, 0, buffer.Length);
  13.                
  14.                 // 将字节数组转换为字符串
  15.                 string message = Encoding.ASCII.GetString(buffer).TrimEnd('\0');
  16.                 Console.WriteLine("Data read from shared memory: " + message);
  17.             }
  18.         }
  19.     }
  20. }
复制代码
代码分析

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


  • 编译并运行 C++ 步调,它将创建共享内存并写入数据。
  • 运行 C# 步调,它将打开并读取共享内存中的数据。
运行效果:


  • C++ 步调输出:Data written to shared memory: Hello from C++!
  • C# 步调输出:Data read from shared memory: Hello from C++!
6、留意事项


  • 定名空间同等性:确保共享内存名称同等,否则 C# 步调无法找到 C++ 步调创建的共享内存。
  • 访问权限:共享内存的访问权限应当在 C++ 和 C# 之间保持同等。
  • 数据格式:在多字节字符的处理惩罚上要确保编码同等,以免出现乱码。
7、应用场景


  • 性能数据传输:实用于大数据量、低耽误的应用场景,如视频处理惩罚、游戏引擎等。
  • 跨进程数据共享:答应多个进程同时访问同一块数据,镌汰数据复制开销。
8、优缺点


  • 长处

    • 高速数据传输,得当大数据量传输场景。
    • 不须要数据序列化与反序列化,低落了性能开销。

  • 缺点

    • 只实用于同一台盘算机上的进程通讯。
    • 须要留意数据同步,克制多个进程同时写入导致的数据竞争。

9、总结

通过共享内存,C# 和 C++ 步调可以大概实现高效的跨进程通讯,实用于高频、大数据量的数据传输需求。共享内存固然具备较高的性能上风,但同时须要妥善管理访问权限和数据同步。
在下一篇文章中,我们将先容 消息队列(Message Queues) 的实现方法,它更得当分布式体系中数据量不大但须要列队处理惩罚的场景。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表