【发布时间】:2015-11-01 04:21:09
【问题描述】:
看来MapViewOfFile增加了文件映射内核对象的引用计数。
引用自MapViewOfFile的MSDN描述:
文件映射对象的映射视图维护内部引用 对象,并且文件映射对象直到全部关闭 对它的引用被释放。因此,要完全关闭文件 映射对象,应用程序必须取消映射文件的所有映射视图 通过调用
UnmapViewOfFile映射对象并关闭文件映射 通过调用CloseHandle处理对象。可以调用这些函数 任何顺序。
另外,来自Windows via C/C++,第 5 版:
前面的代码显示了“预期”的操作方法 内存映射文件。但是,它没有显示的是系统 增加文件对象和文件映射的使用计数 调用
MapViewOfFile时的对象...
尽管如此,我的实际测试表明相反。我在 Windows 10 64 位上使用 Visual Studio 2015。测试程序如下:
#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 在文件映射内核对象的引用计数方面的确切语义是什么。
【问题讨论】:
-
也许在第一次真正打开映射之前不增加句柄使用量是一种优化?
-
我怀疑文档中的暗示(文件映射对象在最后一个直接句柄关闭后仍然可以使用和/或重新打开)是无意的,虽然你确实有取消映射视图以释放所有相关的内核资源,这并不意味着在您实际完成使用映射之前关闭句柄是安全的。 (无论如何,如果您只是保持手柄打开,那么行为是明确的,您无需担心。)
-
@GSerg 我试图实际写入映射视图,然后关闭句柄。但问题依然存在。
标签: c++ windows winapi memory-mapped-files reference-counting