看来MapViewOfFile
增加了文件映射内核对象的引用计数。
从MapViewOfFile
的MSDN描述引用:
文件映射对象的映射视图维护对该对象的内部引用,并且一个文件映射对象不会closures,直到释放所有引用为止。 因此,要完全closures文件映射对象,应用程序必须通过调用
UnmapViewOfFile
来取消映射文件映射对象的所有映射视图,并通过调用CloseHandle
closures文件映射对象CloseHandle
。 这些function可以按任何顺序调用。
另外,从Windows通过C / C ++,第5版 :
上面的代码显示了操作内存映射文件的“预期”方法。 但是,它没有显示的是,当您调用
MapViewOfFile
时,系统递增文件对象和文件映射对象的使用计数…
尽pipe如此,我的实际testing却暗示相反的情况。 我在Windows 10 64位上使用Visual Studio 2015。 testing程序如下:
#include <windows.h> int main() { HANDLE h = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 128, "test"); void* p_memory = MapViewOfFile(h, FILE_MAP_WRITE, 0, 0, 0); CloseHandle(h); h = OpenFileMappingA(FILE_MAP_WRITE, FALSE, "test"); DWORD dw = GetLastError(); // ERROR_FILE_NOT_FOUND }
OpenFileMapping
调用失败,最后一个错误ERROR_FILE_NOT_FOUND
。 当我删除CloseHandle
调用时,一切都会好起来的。 这意味着CloseHandle
调用消除了文件映射内核对象的最后引用计数并将其销毁。 这又意味着MapViewOfFile
实际上不增加对象的引用计数。
我想确定发生了什么事情,以及MapViewOfFile
关于文件映射内核对象的引用计数的确切语义是什么。
通过使用文件作为后备存储而不是分页文件,可以使其更具说服力:
int main() { const char* path = "mmf.bin"; DeleteFile(path); HANDLE hFile = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_FLAG_DELETE_ON_CLOSE, NULL, CREATE_NEW, 0, NULL); HANDLE h = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 0, 128, "test"); int* p_memory = (int*)MapViewOfFile(h, FILE_MAP_WRITE, 0, 0, 128); CloseHandle(h); DWORD attr = GetFileAttributes(path); if (attr != INVALID_FILE_ATTRIBUTES) puts("File still exists"); else puts("File is gone"); }
输出:文件不见了
所以“系统递增文件对象的使用次数”是绝对不正确的。 而且我认为你反驳说它增加了文件映射对象上的使用计数。 不知道该怎么做,里奇特经常不会弄错。 这本书的勘误也没有。 它可能在Windows的早期版本中以这种方式工作,不确定,因为我从来没有故意错误。 我们将不得不坚持SDK文档实际所说的内容:
共享文件映射对象不会被销毁,直到所有使用它的进程都通过CloseHandle函数关闭它们的句柄。