我注意到在Windows(.exe或.dll)上执行文件时,它已被锁定,无法删除,移动或修改。
另一方面,Linux不会锁定正在执行的文件,而可以删除,移动或修改它们。为什么Windows在Linux不锁定时会锁定?锁定是否有优势?
答案 0 :(得分:102)
Linux有一个引用计数机制,因此您可以在文件执行时删除该文件,只要某个进程(以前打开它)有一个打开的句柄,它就会继续存在。删除文件时,将删除该文件的目录条目,因此无法再打开该文件,但已使用该文件的进程仍可使用该文件。一旦使用此文件的所有进程终止,该文件将自动删除。
Windows没有此功能,因此强制锁定文件,直到从中执行所有进程完成为止。
我认为Linux行为更可取。可能有一些深层的体系结构原因,但我发现最引人注目的主要(和简单)原因是,在Windows中,您有时无法删除文件,您不知道为什么,而您所知道的只是某些进程将其保留在使用。在Linux中它永远不会发生。
答案 1 :(得分:28)
据我所知,linux 在运行时锁定可执行文件 - 然而,它会锁定inode。这意味着您可以删除“文件”,但inode仍在文件系统上,不受影响,您真正删除的只是一个链接。
Unix程序一直使用这种思考文件系统的方式,创建一个临时文件,打开它,删除名称。您的文件仍然存在,但该名称已释放供其他人使用,其他任何人都无法看到它。答案 2 :(得分:23)
Linux会锁定文件。如果您尝试覆盖正在执行的文件,您将获得“ETXTBUSY”(文本文件繁忙)。但是,您可以删除该文件,并且内核将在删除最后一次引用时删除该文件。 (如果机器没有干净地关闭,那么当检查文件系统时,这些文件是“删除的inode没有d时间”消息的原因,它们没有被完全删除,因为正在运行的进程有一个对它们的引用,现在他们是。)
这有一些主要优点,您可以升级正在运行的进程,删除可执行文件,替换它,然后重新启动进程。甚至可以像这样升级init,替换可执行文件,并向它发送一个信号,它将重新执行()本身,而不需要重新启动。 (这通常由您的包管理系统自动完成,作为其升级的一部分)
在Windows下,替换正在使用的文件似乎是一个很大的麻烦,通常需要重新启动才能确保没有进程正在运行。
可能存在一些问题,例如,如果您有一个非常大的日志文件,并且您将其删除,但忘记告诉正在登录该文件的进程重新打开该文件,它将保留该引用,并且您我想知道为什么你的磁盘没有突然获得更多的可用空间。
你也可以在linux下使用这个技巧来获取临时文件。打开文件,删除它,然后继续使用该文件。当您的流程退出时(无论出于何种原因 - 甚至断电),该文件将被删除。
像lsof和fuser这样的程序(或者只是在/ proc // fd中查找)可以显示哪些进程打开了不再具有名称的文件。
答案 3 :(得分:6)
我认为你对Windows过于绝对。通常,它不会为可执行文件的代码部分分配交换空间。相反,它保持对可消除的& DLL文件。如果再次需要丢弃代码页,则只需重新加载它们。但是使用/ SWAPRUN,这些页面将保持交换状态。这用于CD或网络驱动器上的可执行文件。因此,Windows不需要锁定这些文件。
对于.NET,请查看Shadow Copy。
答案 4 :(得分:5)
我认为linux / unix不使用相同的锁定机制,因为它们是作为多用户系统从头开始构建的 - 预计多个用户可能使用相同的文件,甚至可能用于不同的目的。
锁定有优势吗?好吧,它可能会减少操作系统必须管理的指针数量,但是现在一天的节省量几乎可以忽略不计。我能想到锁定的最大优点是:你保存了一些用户可见的歧义。如果用户a正在运行二进制文件,并且用户b删除它,那么实际文件必须坚持到用户A的进程完成为止。然而,如果用户B或任何其他用户在文件系统上查找它,他们将无法找到它 - 但它将继续占用空间。对我来说并不是一个太大的问题。
我认为这主要是关于向后兼容窗口文件系统的问题。
答案 5 :(得分:1)
如果文件中执行的代码是否应该被锁定是一个设计决定而MS只是决定锁定,因为它在实践中具有明显的优势:这样你就不需要知道哪个版本使用的是哪个代码哪个应用程序这是Linux默认行为的一个主要问题,大多数人都忽略了这一点。如果更换系统范围的库,你不能轻易知道哪些应用程序使用这些库的代码,大多数时候你能得到的最好的是包管理器知道这些库的一些用户并重新启动它们。但这只适用于一般和熟知的事情,如Postgres及其libs等。更有趣的情况是,如果您针对某些第三方库开发自己的应用程序并且那些被替换,因为大多数情况下包管理器根本不知道您的应用程序。这不仅仅是原生C代码的问题,几乎所有东西都会发生:只需使用带有mod_perl的httpd和使用包管理器安装的一些Perl库,让包管理器因为任何原因更新那些Perl库。它不会重新启动你的httpd,只是因为它不知道依赖项。有很多像这样的例子,因为任何文件都可能包含任何运行时在内存中使用的代码,想想Java,Python和所有这些东西。
因此,有一个很好的理由认为默认锁定文件可能是一个不错的选择。不过,你不需要同意这些理由。
那么MS做了什么?他们只是创建了一个API,使调用应用程序有机会决定是否应该锁定文件,但他们认为此API的默认值是为第一个调用应用程序提供独占锁。查看围绕CreateFile及其dwShareMode
参数的API。这就是为什么你可能无法删除某些应用程序正在使用的文件的原因,它根本不关心你的用例,使用了默认值,因此Windows获得了一个文件的独占锁。
请不要相信人们告诉你一些关于Windows不使用引用计数或不支持硬链接等的东西,这是完全错误的。几乎所有使用HANDLEs的API都记录了它关于引用计数的行为,你几乎可以在任何关于NTFS的文章中轻松阅读它所支持的硬链接并且总是如此。自Windows Vista起,它也支持Symlinks,并通过向read all of those for a given file等提供API来改进对硬链接的支持。
此外,您可能只想查看用于描述文件的结构,例如:与Ext4的NTFS相比,article有很多共同之处。两者都使用扩展区的概念,它将数据与文件名等属性分开,而inode几乎只是旧的,但类似概念的另一个名称。甚至维基百科也在其Wikipedia中列出了两个文件系统。
与网络上的其他操作系统相比,Windows中存在大量关于文件锁定的FUD,就像碎片整理一样。只需阅读{{3}}上的一些内容即可排除部分FUD。
答案 6 :(得分:0)
NT变种有
openfiles
命令,它将显示哪些进程具有哪些文件句柄。但是,它确实需要启用系统全局标志“维护对象列表”
openfiles / local /?
告诉您如何执行此操作,并且这样做会导致性能下降。
答案 7 :(得分:0)
可执行文件在运行时逐步映射到内存。这意味着可执行文件的部分是根据需要加载的。如果在映射所有部分之前交换文件,则可能导致严重不稳定。