我对共享内存感到陌生,我正在寻找一个有效的例子,我只能找到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()
”发布它。我的问题究竟在哪里?
如果它同时存在,操作系统是否会在地址完全释放之前对地址保留一些引用计数?
来自MSDN:
它还减少了相应物理页面的共享计数
让我对实际应该做的事情感到有些困惑。
答案 0 :(得分:3)
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366537%28v=vs.85%29.aspx
CreateFileMapping函数
为指定文件创建或打开命名或未命名的文件映射对象 ...
创建文件映射对象实际上并不将视图映射到进程地址空间。 MapViewOfFile和MapViewOfFileEx函数将文件视图映射到进程地址空间 ...
文件映射对象的映射视图维护对象的内部引用,并且文件映射对象在释放对它的所有引用之前不会关闭。因此,要完全关闭文件映射对象,应用程序必须通过调用UnmapViewOfFile取消映射文件映射对象的所有映射视图,并通过调用CloseHandle来关闭文件映射对象句柄。可以按任何顺序调用这些函数。
因此,Process#1在操作系统中创建了一个地图对象 。然后,流程#1将其中的一部分映射到它自己的流程存储器中
进程#2获取同一操作系统映射对象的句柄,并将相同部分或不同部分映射到它自己的内存中。
当任一进程完成时,它们会调用UnmapViewOfFile
从其自己的进程内存中删除映射,并在其操作系统映射的句柄上调用CloseHandle
。 Windows句柄都是有效引用计数的,因此当所有具有句柄调用CloseHandle
的进程时,操作系统会自动销毁地图对象。
请注意,这意味着如果进程#1创建映射,使用映射,然后完全关闭它,然后进程#2尝试打开该映射,进程#2将失败,因为操作系统在没有进程时删除它任何句柄。要解决此问题,请在文件系统中创建文件以备份内存,这样可以让内存在进程之间保持不变,直到删除文件为止。
答案 1 :(得分:1)
调用MapViewOfFile的每个进程在使用共享内存完成后都应该调用UnmapViewOfFile。这通常是在程序关闭的时候。