我注意到在Windows(.exe或.dll)上执行文件时,该文件已锁定,无法删除,移动或修改。
另一方面,Linux不会锁定执行文件,您可以删除,移动或修改它们。
为什么Windows在Linux不锁定时锁定?锁定有优势吗?
我注意到在Windows(.exe或.dll)上执行文件时,该文件已锁定,无法删除,移动或修改。
另一方面,Linux不会锁定执行文件,您可以删除,移动或修改它们。
为什么Windows在Linux不锁定时锁定?锁定有优势吗?
Answers:
Linux具有引用计数机制,因此您可以在文件执行时删除它,并且只要某个进程(先前打开过该文件)具有打开的句柄,该文件就会继续存在。该文件的目录条目在删除时将被删除,因此无法再打开它,但是已经在使用此文件的进程仍可以使用它。一旦使用该文件的所有进程终止,该文件将被自动删除。
Windows没有此功能,因此它被迫锁定文件,直到从该文件执行的所有进程完成为止。
我相信Linux行为是可取的。可能有一些深层的体系结构原因,但是我发现最引人注目的主要(简单)原因是在Windows中,您有时无法删除文件,您不知道为什么,而且您所知道的只是某些过程将其保留在其中。使用。在Linux中,它永远不会发生。
FILE_SHARE_DELETE
位置1,则可以在打开文件时将其删除。我认为PE加载程序(加载EXE和DLL)不会设置此位。这些句柄是按引用计数的,在删除最后一个句柄时,文件会消失,但是与Unix之间的区别是,当这种情况发生时,NT将阻止使用相同名称创建新文件。
据我所知,Linux 在运行时会锁定可执行文件,但是会锁定inode。。这意味着您可以删除“文件”,但是inode仍在文件系统上,没有被修改,而您真正删除的只是一个链接。
Unix程序始终使用这种思考文件系统的方式,创建一个临时文件,将其打开,然后删除该名称。您的文件仍然存在,但已释放该名称供其他人使用,其他人都看不到它。
Linux确实会锁定文件。如果您尝试覆盖正在执行的文件,则会得到“ ETXTBUSY”(文本文件忙)。但是,您可以删除该文件,并且在删除对该文件的最后一个引用时,内核将删除该文件。(如果未彻底关闭计算机,则在检查文件系统时,这些文件是“删除的inode的d时间为零”消息的原因,它们没有被完全删除,因为正在运行的进程已对其进行引用,现在他们是。)
这具有一些主要优点,您可以通过删除可执行文件,替换可执行文件然后重新启动进程来升级正在运行的进程。甚至init都可以像这样进行升级,替换可执行文件,并向其发送信号,然后它将重新执行exec()本身,而无需重新启动。(这通常是软件包管理系统在升级过程中自动完成的)
在Windows下,替换正在使用的文件似乎很麻烦,通常需要重新启动以确保没有进程在运行。
可能会有一些问题,例如,如果您有一个非常大的日志文件,并且将其删除了,但是却忘记告诉正在记录到该文件的进程来重新打开该文件,它将保存引用,您会怀疑为什么您的磁盘没有突然获得更多可用空间。
您也可以在Linux下使用此技巧来存储临时文件。打开文件,将其删除,然后继续使用该文件。当您的进程退出时(无论出于何种原因-甚至是电源故障),该文件都会被删除。
诸如lsof和fuser之类的程序(或只是在/ proc // fd中四处浏览)可以向您显示哪些进程中打开的文件不再具有名称。
我认为linux / unix不会使用相同的锁定机制,因为它们是作为多用户系统从头开始构建的-希望有多个用户使用同一文件,甚至可能出于不同的目的。
锁定有优势吗?好吧,它可能会减少操作系统必须管理的指针数量,但是现在节省的数量几乎可以忽略不计。我可以想到的最大的锁定优势是:您可以节省一些用户可见的歧义。如果用户a正在运行二进制文件,并且用户b将其删除,则实际文件必须一直保留到用户A的过程完成为止。但是,如果用户B或任何其他用户在文件系统上寻找它,他们将无法找到它-但它将继续占用空间。对我而言,这并不是真正的大问题。
我认为很大程度上是与window的文件系统向后兼容的问题。
我认为您对Windows太过绝对了。通常,它不会为可执行文件的代码部分分配交换空间。而是,它在可执行文件和DLL上保持锁定。如果再次需要废弃的代码页,则只需重新加载它们即可。但是,使用/ SWAPRUN,这些页面将保持交换状态。这用于CD或网络驱动器上的可执行文件。因此,Windows不需要锁定这些文件。
对于.NET,请查看Shadow Copy。
如果要锁定文件中的已执行代码是设计决定,而MS只是决定锁定,因为它在实践中具有明显的优势:这样,您无需知道哪个应用程序使用哪个版本的代码。这是Linux默认行为的一个主要问题,大多数人只是将其忽略。如果替换了系统范围的库,您将不容易知道哪些应用程序使用了这些库的代码,大多数情况下,您可以获得的最好的好处是,程序包管理器了解这些库的某些用户并重新启动它们。但这仅适用于一般的众所周知的事情,例如Postgres及其库等。更有趣的情况是,如果您针对某些第三方库开发自己的应用程序,而这些库则被替换了,因为大多数情况下,程序包管理器根本不了解您的应用程序。然后' 这不仅是本机C代码之类的问题,而且几乎所有情况都可能发生:只需将httpd与mod_perl一起使用,并使用软件包管理器安装一些Perl库,并让软件包管理器出于任何原因更新这些Perl库。它不会因为您不知道依赖关系而重启您的httpd。有很多这样的例子,仅仅是因为任何文件都可能包含任何运行时正在内存中使用的代码,请考虑一下Java,Python和所有类似的东西。
因此,有充分理由认为默认情况下锁定文件可能是一个不错的选择。不过,您无需同意这些理由。
那么MS做了什么?他们只是创建了一个API,使调用应用程序有机会决定是否应锁定文件,但是他们决定此API的默认值是为第一个调用应用程序提供排他锁。看看有关CreateFile的API及其dwShareMode
参数。这就是为什么您可能无法删除某些应用程序正在使用的文件的原因,它根本不在乎您的用例,使用的是默认值,因此被Windows独占锁定。
请不要相信有人告诉您有关Windows的信息,而不是在句柄上使用引用计数或不支持硬链接等,这是完全错误的。几乎每个使用HANDLEs的API都记录了其与引用计数有关的行为,您几乎可以在几乎所有有关NTFS的文章中轻松地阅读到,它的确支持硬链接并且始终支持。从Windows Vista开始,它还支持符号链接,并且通过提供API来读取给定文件的所有API的方式,对硬链接的支持也得到了改进。。
此外,与NTFS相比,您可能只想看看Ext4中用于描述文件的结构,而NTFS具有许多共同点。两者都适用于扩展区的概念,该区将数据与诸如文件名之类的属性分开,而inode几乎只是一个较旧但类似的概念的另一个名称。甚至Wikipedia在其文章中也列出了这两种文件系统。
与网络上的其他操作系统相比,Windows中的文件锁定确实存在很多FUD,就像磁盘碎片整理一样。只需阅读一下Wikipedia,就可以排除某些FUD 。
WinSxS
东西。此外,这不是要把它们加载到内存中并保存在那里,Windows也会在必要时做到这一点,而是要知道并确定是否应该替换文件,以及由谁来决定。Windows-API只是让文件的第一个用户决定,这很有意义。