进程间通讯(五)--共享内存(文件映射)

时间:2022-05-14 10:15:34
在Windows中,在同一台机器上共享数据的最底层的机制就是内存映射文件。所以,所有进程间通讯机制,都会用到内存映射文件。
这种数据共享机制是通过让两个或多个进程映射同一个文件映射对象得视图实现的,这意味着在进程间共享相同的物理存储界面。因此,当一个进程在文件映射对象视图中写入数据的时候,其他进程会在它们的视图中立刻看到变化。注意在多个进程共享同一个文件映射对象来说,所有进程使用的文件映射对象的名称必须相同。
函数解释:
打开一个映射文件对象
HANDLE CreateFileMapping(
HANDLE hFile, // 一个文件的句柄

LPSECURITY_ATTRIBUTES lpAttributes, // 定义内存映射文件对象是否可以继承

DWORD flProtect, // 该内存映射文件的保护类型

DWORD dwMaximumSizeHigh, // 内存映射文件的长度

DWORD dwMaximumSizeLow,

LPCTSTR lpName // 内存映射文件的名字

);


如果创建共享内存,其他对象不能再创建相同名字映射对象,要用以下函数去打开以及创建好的对象
HANDLE OpenFileMapping(
DWORD dwDesiredAccess, // 指定保护类型

BOOL bInheritHandle, // 返回的句柄是否可被继承

LPCTSTR lpName // 创建对象时使用的名字

);


为文件内容分配线性地址空间
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // 前两个函数返回的内存映射文件对象的句柄

DWORD dwDesiredAccess, // 指定保护类型,可以是FILE_MAP_WRITE、FILE_MAP_READ

DWORD dwFileOffsetHigh, // 从文件的那个地址开始映射

DWORD dwFileOffsetLow,

SIZE_T dwNumberOfBytesToMap // 要映射的字节数,如果指定为0 则映射整个文件

);


撤销映射
BOOL UnmapViewOfFile (LPCVOID lpBaseAddress );

将数据立刻写入磁盘
BOOL FlushViewOfFile(
LPCVOID lpBaseAddress, // 开始的地址

SIZE_T dwNumberOfBytesToFlush // 数据块的大小

);

#include "stdafx.h"
#include <Windows.h>

int main()
{
WCHAR FileMappingName[] = L"ShareMemory";//内存映射名称
char BufferData[] = "This is a Demo!"; //共享内存数据
LPVOID Buffer; //共享内存指针

//打开一个文件映射对象
HANDLE FileMappingHandle = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, FileMappingName);
if (FileMappingHandle!=NULL)
{
//创建映像对象的视图
Buffer = MapViewOfFile(FileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
printf("共享内存数据:%s\r\n",(char*)Buffer);
}
else
{
//如果没有打开文件映射对象,则创建一个映射对象
FileMappingHandle = CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
strlen(BufferData)+1,
FileMappingName
);
//创建映像视图
Buffer = MapViewOfFile(FileMappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
//将共享的数据拷入共享内存
strcpy((char*)Buffer, BufferData);
printf("写入内存数据:%s\r\n", (char*)BufferData);
}

getchar();//这里拦住程序不让其退出,否则进程一旦退出则销毁所有句柄

//解除文件映射,关闭内存映射句柄
UnmapViewOfFile(Buffer);
CloseHandle(FileMappingHandle);
return 0;
}
连续两次运行该实例,可发现两个进程共享了内存数据。