创建文件FILE_FLAG_DELETE_ON_CLOSE在关闭任何句柄后失败

CreateFile FILE_FLAG_DELETE_ON_CLOSE fails after any handle has been closed

本文关键字:任何 句柄 失败 CLOSE FILE 文件 FLAG DELETE ON 创建      更新时间:2023-10-16

我们创建一个用作内存映射文件的文件。

我们以GENERIC_READ | GENERIC_WRITE
开场我们使用与FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
共享我们使用文件属性FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE

我们成功创建文件。我们可以根据需要使用相同的标志多次重新打开它。

关闭一个句柄后,我们无法再打开任何句柄,它会返回ERROR_ACCESS_DENIED。我们可以通过关闭任何句柄来引起这种情况,第一个来自 CreateFile(ALWAYS_CREATE),或者来自 CreateFile(OPEN_EXISTING) 的其他句柄。

有什么办法可以避免这种情况吗?我们使用 memoryMappedFile 作为必须共享资源的不同进程之间的通信。这些进程有时会启动和停止。现在,一旦我们关闭一个句柄,我们就无法打开内存映射文件。

我尝试将打开的调用更改为使用 FILE_ATTRIBUTE_NORMAL,因此只有创建调用使用 CLOSE_ON_DELETE但这对这种情况没有影响。

您遇到的问题是,一旦关闭了使用 FILE_FLAG_DELETE_ON_CLOSE 打开的文件句柄,操作系统将不再允许创建新句柄。

血腥的细节:当为打开的关闭时删除的文件处理IRP_MJ_CLEANUP(这就是发生句柄关闭的情况),Windows 文件系统将在文件对象上设置一个内部标志,指示它正在出路。 随后对文件的打开尝试将失败,并显示 STATUS_DELETE_PENDING ,Win32 子系统将映射到您看到的 Win32 ERROR_ACCESS_DENIED代码。

对于您的用例,您可能需要考虑使用命名共享内存 (MSDN) 模式。 基本上,让操作系统管理共享内存的空间。 只需确保应用适当的安全属性,就可以开始了。

事实证明,令人尊敬的Raymond Chen在他的Microsoft开发博客The Old New Thing上回复了这个问题。Bukes是正确的,但作为替代方案,正如Raymond在他的文章中所说:

看起来他们真的希望文件保持有效(包括允许进一步的 CreateFile 调用成功),只要任何打开的句柄继续引用该文件。幸运的是,客户只需要句柄来创建内存映射视图。文件指针并不重要。因此,客户可以使用 DuplicateHandle 而不是 CreateFile 来获取文件的其他句柄。由于所有句柄都引用同一个文件对象,因此在关闭所有句柄之前,文件对象不会删除该文件。