Lin*_*gxi 6 c++ windows winapi reference-counting memory-mapped-files
似乎MapViewOfFile增加了文件映射内核对象的引用计数.
引自MSDN描述MapViewOfFile:
文件映射对象的映射视图维护对象的内部引用,并且文件映射对象在释放对它的所有引用之前不会关闭.因此,要完全关闭文件映射对象,应用程序必须通过调用
UnmapViewOfFile并通过调用并关闭文件映射对象句柄来取消映射文件映射对象的所有映射视图CloseHandle.可以按任何顺序调用这些函数.
此外,从Windows到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关于文件映射内核对象的引用计数的确切语义是什么.
通过使用文件作为后备存储而不是页面文件,可以使其更具说服力:
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");
}
输出:文件不见了
因此,“系统增加文件对象的使用计数”绝对是不正确的。而且我认为您不赞成这样做会增加文件映射对象的使用计数。不知道该怎么做,Richter不会经常出错。这本书的勘误表也没有。在早期版本的Windows中,它可能以这种方式工作,所以不确定,因为我从来没有故意出错。我们必须坚持SDK文档的实际含义:
共享文件映射对象只有在使用它的所有进程通过使用CloseHandle函数关闭它们的句柄之后,才会被销毁。
| 归档时间: | 
 | 
| 查看次数: | 579 次 | 
| 最近记录: |