如何在窗口下正确使用共享内存

How to use shared memory correctly under windows

本文关键字:共享 内存 窗口      更新时间:2023-10-16

我对共享内存有点陌生,我正在寻找一个工作示例,我设法只通过 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:

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

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

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

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

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

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

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