等待文件可写

时间:2015-03-02 09:55:18

标签: winapi

我正在开发一种将数据写入文件的工具。

在某些时候,文件可能会被锁定"并且在其他句柄关闭之前不可写。

我可以在循环中使用CreateFile API,直到该文件可用于写访问。

但我在循环中使用CreateFile有两个问题:

  • Harddrive(缓存)一直在运行......?!
  • 我需要再次调用CreateFile以获得带有不同标志的有效书写句柄......?!

所以我的问题是:

等待文件可写并立即获得有效句柄的最佳解决方案是什么?

是否有任何事件解决方案或任何事项,允许"排队/保留"对于一个句柄,所以没有"不受控制的"与他人竞争?

2 个答案:

答案 0 :(得分:3)

文件可以被锁定"有两个原因:

  1. 一个实际的文件锁,它可以阻止写入文件并可能从中读取文件。
  2. 正在打开的文件没有共享访问权限(意外或自愿)甚至阻止您打开句柄。如果您已经看到CreateFile失败了,那可能就是这种情况,而不是真正的锁定。
  3. 概念上 [1] 至少有两种方法可以知道没有其他进程在没有繁忙等待的情况下锁定文件:

    1. 找出谁持有锁并等待进程或线程退出(或者直接杀死它们......)
    2. 自行锁定文件
    3. 谁拥有锁?
      找出关于锁拥有者是相当讨厌的,你可以通过完全未记录的 SystemLocksInformation类与未记录的NtQuerySystemInformation函数一起使用(后者是"只有未记录的& #34;,但前者是如此无证,以至于很难找到任何信息。返回的结构解释为here,它包含一个拥有的线程ID。

      幸运,拿着一把锁假装握住一个把柄。关闭文件句柄将解锁所有文件范围。这意味着:没有手柄没有锁。

      换句话说,问题也可以表示为"谁持有文件的开放句柄?" 。当然,并非所有持有文件句柄的进程都会锁定文件,但没有进程的进程可以保证没有进程锁定文件。
      查找哪些进程打开文件的代码(使用重启管理器)更容易,并且在Raymond Chen的网站上readily available

      现在您知道哪些进程和线程正在保存文件句柄和锁,请创建所有线程/进程句柄的列表,并在进程句柄列表中使用WaitForMultipleObjects。当进程退出时,所有句柄都将关闭 这也透明地处理了锁定"的可能性。因为进程不共享访问权限。

      自行锁定文件
      您可以使用LockFileEx,它以异步方式运行。请注意,LockFileEx需要一个使用 读取或写入权限打开的有效句柄(获取写入权限可能无法实现,但读取应该几乎始终有效 - 即使您被阻止从实际读取通过独占锁定,如果没有锁定,它仍然可以创建可以读取的句柄

      然后,您可以等待异步锁定通过OVERLAPPED结构中的事件或完成端口完成,甚至可以同时执行其他有用的操作。锁定文件后,您就知道没有其他人将其锁定。

      <小时/> [1] 措辞&#34;概念上&#34; 表明我非常确定这两种方法都有效,但我没有对它们进行过测试。

答案 1 :(得分:1)

除了繁忙的循环之外,反复尝试打开具有写访问权限的文件(它没有正确的味道 - 如果文件被卡住的进程锁定并需要重启或手动终止,那么你&# 39;永远不能写信给它。

您可以写入临时文件并在之后重命名(您可以告诉操作系统需要文件重命名操作,它将在下次启动时执行)。如果你需要附加而不是写,那么你必须编写一个进程来将你的临时文件附加到正确的文件,可能是在启动时(写下哪个文件的说明附加到你的进程文件的哪个位置)阅读)。

如果您需要修改锁定的文件,那么您只需要尽快锁定它,如果您没有写入权限则拒绝启动该程序 - 警告用户就在开始。

有可能您可以更好地等待:如果文件被锁定以进行写入,您可以假设有人要写入,因此使用FindFirstChangeNotification接收FILE_NOTIFY_CHANGE_LAST_WRITE或FILE_NOTIFY_CHANGE_ATTRIBUTES事件的事件。它并不完美,因为有人可以要求独家阅读。

我想你可以尝试获取锁定文件的句柄并等待它,所以当它被释放时,WaitForSingleObject将返回。但是,很有可能不允许您获得由不同进程(由安全子系统)拥有的句柄