Windows进程通信之共享内存通信

本文章先介绍共享内存是啥,再介绍使用共享内存要涉及的4个函数,最后将实例代码附上,实例代码用于加深理解,读者也可以模仿用例改编使用。

1. 共享内存的简单介绍 

共享内存就是允许两个不相关的进程访问同一个虚拟内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。

共享内存,存在于每个进程的进程地址空间中,属于每个进程,由于它并不需要系统调用干预和数据复制,它的效率是非常高的,它比我们所学的几种IPC机制(信号量,管道,消息队列)都要快。虽然它性能最好,但是它不提供同步互斥机制,因此需要我们程序员来提供,带来了编程的难度。这也是其他IPC机制存在的原因~

总结以上我们可以得出下面3点:

1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝。

2)为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将其映射到自己的私有地址空间。进程就可以直接读写这一块内存而不需要进行数据的拷贝,从而大大提高效率。

3)由于多个进程共享一段内存,因此也需要依靠某种同步机制

2. 共享内存涉及的函数

使用共享内存主要用到四个函数。下面是这些函数的原型和使用说明。

1)CreateFileMapping

函数功能:创建一个新的文件映射内核对象。即创建内存映射文件,将上述真正存在的物理文件映射成为一个虚拟的映射文件,就是把物理文件与虚拟文件绑定。

函数原型:

HANDLE CreateFileMapping(
  HANDLE hFile,                       //物理文件句柄
  LPSECURITY_ATTRIBUTES lpAttributes, //安全设置
  DWORD flProtect,                    //保护设置
  DWORD dwMaximumSizeHigh,            //高位文件大小
  DWORD dwMaximumSizeLow,             //低位文件大小
  LPCTSTR lpName                      //共享内存名称
);

参数说明:

hFile:任何可以获得的物理文件句柄。

a)如果你需要创建一个物理文件无关的内存映射也无妨, 将它设置成为 0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了。使用 INVALID_HANDLE_VALUE还需要设置需要申请的内存空间的大小, 无论物理文件句柄参数是否有效, 这样 CreateFileMapping 就可以创建一个和物理文件大小无关的内存空间给你, 甚至超过实际文件大小, 如果你的物理文件有效, 而大小参数为0, 则返回给你的是一个和物理文件大小一样的内存空间地址范围.  返回给你的文件映射地址空间是可以通过复制, 集成或者命名得到, 初始内容为0。

b) 如果需要和物理文件关联, 要确保你的物理文件创建的时候的访问模式和"保护设置"匹配, 比如: 物理文件只读, 内存映射需要读写就会发生错误. 推荐你的物理文件使用独占方式创建。(调用CreateFile函数创建,将其返回值赋值给hFile即可)

lpAttributes:安全设置,一般设置NULL就可以了, 使用默认的安全配置。

flProtect:当文件映射时读写文件的属性。其值为下述常数之一:

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用共享内存进行进程间通信的客户端和服务端的示例代码,代码中包括了创建和映射共享内存,以及读写共享内存的基本操作。 服务端代码: ``` #include <windows.h> #include <stdio.h> int main() { HANDLE hMapFile; LPCTSTR pBuf; // 创建共享内存 hMapFile = CreateFileMapping( INVALID_HANDLE_VALUE, // 使用无效的句柄 NULL, // 默认安全级别 PAGE_READWRITE, // 可读写 0, // 高位字节数 1024, // 低位字节数 TEXT("MyFileMappingObject")); // 共享内存名称 if (hMapFile == NULL) { printf("CreateFileMapping failed (%d)\n", GetLastError()); return 1; } // 映射共享内存 pBuf = (LPTSTR)MapViewOfFile( hMapFile, // 共享内存句柄 FILE_MAP_ALL_ACCESS,// 可读写 0, 0, 1024); if (pBuf == NULL) { printf("MapViewOfFile failed (%d)\n", GetLastError()); CloseHandle(hMapFile); return 1; } // 从共享内存中读取数据 printf("Buf: %s\n", pBuf); // 写入数据到共享内存 CopyMemory((LPVOID)pBuf, "Hello from server!", sizeof("Hello from server!")); // 解除映射 UnmapViewOfFile(pBuf); // 关闭句柄 CloseHandle(hMapFile); return 0; } ``` 客户端代码: ``` #include <windows.h> #include <stdio.h> int main() { HANDLE hMapFile; LPCTSTR pBuf; // 打开共享内存 hMapFile = OpenFileMapping( FILE_MAP_ALL_ACCESS, // 可读写 FALSE, // 不继承 TEXT("MyFileMappingObject")); // 共享内存名称 if (hMapFile == NULL) { printf("OpenFileMapping failed (%d)\n", GetLastError()); return 1; } // 映射共享内存 pBuf = (LPTSTR)MapViewOfFile( hMapFile, // 共享内存句柄 FILE_MAP_ALL_ACCESS,// 可读写 0, 0, 1024); if (pBuf == NULL) { printf("MapViewOfFile failed (%d)\n", GetLastError()); CloseHandle(hMapFile); return 1; } // 写入数据到共享内存 CopyMemory((LPVOID)pBuf, "Hello from client!", sizeof("Hello from client!")); // 从共享内存中读取数据 printf("Buf: %s\n", pBuf); // 解除映射 UnmapViewOfFile(pBuf); // 关闭句柄 CloseHandle(hMapFile); return 0; } ``` 此代码演示了如何创建一个共享内存对象,并分别在服务端和客户端中映射到进程地址空间中,然后进行数据读写。在实际应用中,需要根据具体需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值