【问题标题】:Will we ever be able to delete an open file in Windows?我们能否在 Windows 中删除打开的文件?
【发布时间】:2010-07-08 09:41:29
【问题描述】:

免责声明:我主要是 linux/web 开发人员。

Windows 有这个“不错”的功能,它拒绝删除任何进程保持打开的任何文件的权限。因此,如果防病毒软件在错误的时间点击了错误的文件,某些随机程序可能会出现异常行为并可能崩溃。

我说的对吗?有解决此问题的计划吗?

你们中是否有人认为这是可以接受的,或者,当时这怎么可能是个好主意?

编辑:

它在 Unix 上的工作方式非常不同,几十年来一直如此。

举个例子:

  • 进程 1 打开 foo.txt,读取或写入,或两者兼而有之,没关系
  • 进程 2 删除文件
  • 文件与文件系统取消链接
  • 进程 1 继续读取和/或写入,文件仍然存在,只要磁盘上有空间,它就可以增长。它只是无法从其他还没有文件句柄的进程访问。
  • 当进程 1 关闭文件时,将无法从任何地方访问它

实际上,Unix 上临时文件的常见使用模式是:open-remove-read/write-close。

【问题讨论】:

  • 与删除另一个进程使用而没有警告的文件相反,这绝对不会导致该程序行为不端并可能崩溃。有像解锁器这样的程序可以让你关闭文件句柄,但我看不出删除正在使用的文件是个好主意。
  • 但是,如果有人删除了进程 1 正在使用的文件,进程 1 怎么会出现异常或崩溃?该文件仍然存在,可以读取或写入,如果您还没有打开文件句柄,则它不可用。
  • 这只是两个平台不同的众多哲学决策之一。两种方法都有其优点和缺点,尽管我个人认为这两种方法都没有比另一种更好或更差。当你为一个平台开发时,你需要了解它的特性并适当地处理它们。如果你没有这样做并且你的程序崩溃了,那么你的程序有问题,而不是平台。
  • 我的简单回答——在一个由 Windows 主导的世界里,让文件被打开的进程锁定是一件好事!非常理智和理性,请为我锁定更多东西!但是,在一个由 Linux/Unix/跨平台 Java/etc 主导的世界中,由于黑客和变通方法,我们不得不不情愿地瞄准“平台 X”上看似随机的进程锁定文件是纯粹的疯狂精神错乱和随之而来的头发拉扯。记下我的话:就像他们在 HTML5 中的 canvas 标签上投降一样,他们将不得不在某一天投入一些 API 来禁用进程中的这种行为。我可以做梦
  • 看来,截至 2019 年 10 月,这种行为已经改变。 stackoverflow.com/questions/60424732/…

标签: windows


【解决方案1】:

您最初的陈述不正确。 Windows 确实允许删除打开的文件。您只需要指定 FILE_SHARE_DELETE 就可以了。细心的程序员应该明智地决定该标志(或共享用于读/写)是否有意义并通过它。

在启用完全共享(包括删除)的情况下无法打开文件的防病毒产品存在问题。

但是,Windows 会记住任何进程的当前工作目录并防止它被删除。此工作目录与进程打开的任何文件的位置无关。

【讨论】:

  • 如果这是对Windows所做的道歉,我认为这是有缺陷的。任何程序都可以破坏任何其他程序,而无需这样做。刚刚在目录上打开的文件管理器会破坏尝试删除并重新创建同一目录的安装程序。
  • @eudoxos:关于“在文件管理器中打开”,但情况似乎并非如此。至少 Windows 资源管理器不会阻止其当前显示的文件夹被删除。
  • @eudoxos:那是 Double Commander 中的一个错误(功能?)。确实,您应该在相应的开发人员处开一张票 :)
  • @eudoxos:这是一个不同的问题(与工作目录有关)。尽管 Windows 可以支持它,但不允许这样做是一个设计决定。 technet.microsoft.com/en-us/magazine/…
  • 不错的链接。他们挖掘了极端案例,结合 DLL 地狱(在 Linux 下,.so 的次要版本是二进制兼容的;主要版本可以一起安装)使决策合乎逻辑。很高兴知道他们至少意识到了这个问题。
【解决方案2】:

这是完全可以接受的。想象这样一种情况,您正在应用程序中读取数据库文件,而其他一些应用程序出现并从您的正下方删除该数据库文件。您的应用程序如何知道检查该文件是否仍然存在?它将如何确保文件流不会突然尝试读取该文件可能存在一毫秒,但不是下一毫秒?这就是程序可以锁定文件的原因,以确保文件始终存在,直到程序确定它已完成。

告诉我们为什么在您的情况下不希望使用此文件锁定可能会更有帮助。我很确定防病毒程序会对文件进行乐观锁定,除非它正在清理它们。

【讨论】:

  • 这就像从房子下面拉出地基。
  • 每个文件 I/O 操作都可能发出错误信号,因此除非您检查它们时马虎,否则不会执行其他检查。
  • 对于那些已经打开文件的人没有任何反应 - 没有读取或写入错误。
  • 在 Linux 文件系统上,删除文件只会删除其在目录列表中的条目。只有在关闭该文件的所有文件描述符后,该文件才会真正被删除。对于已经打开该文件的应用程序而言,该文件仍然存在,因此“[删除]您正下方的数据库文件”不是问题。 (当然,一旦应用程序关闭文件描述符,数据就会被删除,但这是应用程序删除文件的责任,对使用它的应用程序来说不是问题。)
  • @NathanW 在 unix 中,你永远不会得到房子的地基,而是一根绳子系在横梁上。当有人删除文件时,他们的绳索就被切断了。只要有人拿着一根绑在房梁上的绳子,房子就会一直存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多