即使在Windows中关闭句柄后如何读取文件?

时间:2016-08-31 21:18:51

标签: winapi dropbox

我需要在Windows中读取文件并避免任何操作系统级锁定,以便用户即使在我的应用程序正在读取文件时也可以删除该文件。

通过C ++,Python,Java等使用典型的读取操作,通过procmon进行评估时显示相同的Winapi调用序列:

  1. 的CreateFile
  2. ReadFile(多次到"文件结束"到达)
  3. CloseFile
  4. 如果我尝试在步骤1和3之间通过资源管理器删除文件(基本上在CreateFile之后和CloseFile之前),我将使用"文件正在使用"错误。

    但是,我注意到当Dropbox读取要上传到服务器的文件时,序列为:

    1. 的CreateFile
    2. CloseFile
    3. ReadFile的
    4. 重复步骤1-3
    5. 由于在CloseFile之后调用了ReadFile,我甚至可以在Dropbox读取文件时删除该文件。

      我无法弄清楚在调用CloseFile后Winapi如何允许ReadFile。

      我附上了Procmon的截图,其中显示了Dropbox的行为。

      有人知道这是怎么做到的吗?

      Procmon showing Dropbox

1 个答案:

答案 0 :(得分:0)

这种创建 - 关闭 - 读取语义应该由文件映射到应用程序的地址空间中的内存区域的事实引起。当应用程序尝试从该区域读取时,操作系统从文件中读取必要的数据并将其传递给应用程序(数据显示在映射文件的内存区域中)。

内存映射文件由文件映射对象(称为内核世界中的一个部分)支持。给定文件句柄,您可以通过 SELECT 1 as Id, (SELECT * FROM #OR_MK FOR XML PATH('MK'), root('OR_MK') ) as OR_MK ,(SELECT * FROM #OR_CA FOR XML PATH('CA'), root('OR_CA') ) as OR_CA -- ,ISNULL( (SELECT * FROM #OR_RS FOR XML PATH('RS'), root('OR_RS')), (SELECT ISNULL(ContactCode,'') , ISNULL(EmailPaper,'') , ISNULL(ShortEmail,'') , ISNULL(WebSite,'') , ISNULL(Providers,'') FROM #OR_RS FOR XML AUTO)) as OR_RS ,(SELECT * FROM #OR_RS FOR XML PATH('RS'), root('OR_RS')) as OR_RS ,(SELECT * FROM #OR_DC FOR XML PATH('DC'), root('OR_DC') ) as OR_DC ,(SELECT * FROM #BENEFICIARY FOR XML PATH('BEN'), root('BENEFICIARY') ) as BENEFICIARY ,(SELECT * FROM #MK_REPORT for XML PATH('REP'), root('MK_REPORT')) as MK_REPORT 创建此类对象,并通过CreateFileMapping将其映射到您的地址空间(也存在一些Ex变体)。文件映射对象保留对其映射的文件的额外引用。因此,在为文件创建文件映射对象之后,您可以关闭文件句柄并通过文件映射对象读取文件。