Memory-mapping a file in Windows with SHARE attribute (so file is not locked against deletion)

爷,独闯天下 提交于 2019-12-10 19:51:24

问题


Is there any way to map a file's content into memory in Windows that does not hold a lock on the file (in particular, such that the file can be deleted while still mmap'd)?

The Java NIO libraries mmap files in Windows in such a way that the mapped file cannot be deleted while there is any non garbage collected MappedByteBuffer reference left in the heap. The JDK team claim that this is a limitation of Windows, but only when files are mmap'd, not when they are opened as regular files:

https://mail.openjdk.java.net/pipermail/nio-dev/2019-January/005698.html

(Obviously if a file is deleted while mmap'd, exactly what should happen to the mmap'd region is debatable in the world of Windows file semantics, though it's well-defined in Linux.)

For reference, the inability to delete files while they are memory mapped (or not yet garbage collected) creates a lot of problems in Java:

http://www.mapdb.org/blog/mmap_files_alloc_and_jvm_crash/

And there are security reasons why an unmap operation is not supported:

https://bugs.openjdk.java.net/browse/JDK-4724038

UPDATE: See also: How to unmap an mmap'd file by replacing with a mapping to empty pages


回答1:


as noted @eryksun we can delete mapped file, if section(file mapping) was created without SEC_IMAGE attribute in 2 ways:

  • open file with FILE_FLAG_DELETE_ON_CLOSE flag - The file is to be deleted immediately after all of its handles are closed, which includes the specified handle and any other open or duplicated handles. or we can use NtOpenFile or NtCreateFile call with flag FILE_DELETE_ON_CLOSE.
  • by call ZwDeleteFile. really internal NtDeleteFile open file with FILE_DELETE_ON_CLOSE flag and special internal disposition DeleteOnly = TRUE. this is make call more efficient compare normal open file and then close it handle.

in code this look like.

#ifndef FILE_SHARE_VALID_FLAGS
#define FILE_SHARE_VALID_FLAGS 0x00000007
#endif

NTSTATUS Delete1(PCWSTR FileName)
{
    HANDLE hFile = CreateFile(FileName, DELETE, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        return RtlGetLastNtStatus();
    }
    CloseHandle(hFile);
    return 0;
}

NTSTATUS Delete2(PCWSTR FileName)
{
    UNICODE_STRING ObjectName;

    if (RtlDosPathNameToNtPathName_U(FileName, &ObjectName, 0, 0))
    {
        OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName };

        NTSTATUS status = ZwDeleteFile(&oa);

        RtlFreeUnicodeString(&ObjectName);

        return status;
    }

    return STATUS_UNSUCCESSFUL;
}

note that call DeleteFileW fail here with status - STATUS_CANNOT_DELETE. i recomendate call RtlGetLastNtStatus() here instead GetLastError() because win32 mapping NTSTATUS to error code is not injective and frequently lost valuable information. say STATUS_CANNOT_DELETE mapped to ERROR_ACCESS_DENIED. but exist huge another NTSATUS codes which also mapped to ERROR_ACCESS_DENIED. the ERROR_ACCESS_DENIED not only STATUS_ACCESS_DENIED (real access denied). got STATUS_CANNOT_DELETE much more informative here compare ERROR_ACCESS_DENIED. the RtlGetLastNtStatus have exactly same signature as GetLastError and exported from ntdll.dll ( so include ntdll.lib or ntdllp.lib)

extern "C" NTSYSCALLAPI NTSTATUS NTAPI RtlGetLastNtStatus();


来源:https://stackoverflow.com/questions/54138684/memory-mapping-a-file-in-windows-with-share-attribute-so-file-is-not-locked-aga

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!