0

我对共享内存有点陌生,我正在寻找一个工作示例,我只能通过MSDN找到

在第一个进程中,我将共享内存声明如下:

hFileMapping = ::CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, dwDataSize, strSharedMemoryName.c_str());
pBuffer = ::MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, dwDataSize);
::CopyMemory(pBuffer, pData, dwDataSize);

在第二个过程中:

HANDLE hFileMap = ::OpenFileMapping(FILE_MAP_READ, FALSE, strContentsSizeFileMap.c_str());
LPVOID pData = ::MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);

我知道一旦我完成了 mapView 的工作,我需要使用“ UnmapViewOfFile()”来释放它。我的问题是具体在哪里?

  1. 父进程?
  2. 子进程
  3. 两个都?

如果两者都存在,操作系统是否会在地址完全释放之前保留一些引用计数?

来自 MSDN:

它还会减少相应物理页面的共享计数

这让我对我实际上应该做什么有点困惑。

4

2 回答 2

3

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366537%28v=vs.85%29.aspx

CreateFileMapping 函数
创建或打开指定文件的命名或未命名文件映射对象。
...
创建文件映射对象实际上并不将视图映射到进程地址空间。MapViewOfFile 和 MapViewOfFileEx 函数将文件视图映射到进程地址空间。
...
文件映射对象的映射视图维护对该对象的内部引用,并且文件映射对象在释放对它的所有引用之前不会关闭。因此,要完全关闭文件映射对象,应用程序必须通过调用UnmapViewOfFile取消映射文件映射对象的所有映射视图,并通过调用CloseHandle关闭文件映射对象句柄. 这些函数可以按任何顺序调用。

所以进程#1在操作系统中创建了一个地图对象。然后进程#1 将其中的一部分映射到它自己的进程内存中。
进程#2 获得同一个操作系统映射对象的句柄,并将该对象的相同部分或不同部分映射到它自己的内存中。
当任一进程完成时,它们调用UnmapViewOfFile从它自己的进程内存中删除映射,并调用CloseHandle它们对操作系统映射的句柄。Windows 句柄都是有效引用计数的,因此当所有具有句柄调用的进程时,CloseHandle操作系统会自动销毁映射对象。

请注意,这意味着如果进程#1 创建映射,使用映射,然后完全关闭它,然后进程#2 尝试打开该映射,进程#2 将失败,因为操作系统在没有进程有任何句柄时将其删除。要解决此问题,请在文件系统中创建文件以支持您的内存,这允许内存在进程之间停留,直到您删除该文件。

于 2015-03-25T16:59:25.210 回答
1

每个调用 MapViewOfFile 的进程在使用完共享内存后都应该调用 UnmapViewOfFile。这通常是在程序关闭时。

于 2015-03-25T16:16:20.937 回答