![为什么我不能像在 Linux/Mac 上那样更改在 Windows 上读取的文件的名称?](https://linux22.com/image/1304644/%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E4%B8%8D%E8%83%BD%E5%83%8F%E5%9C%A8%20Linux%2FMac%20%E4%B8%8A%E9%82%A3%E6%A0%B7%E6%9B%B4%E6%94%B9%E5%9C%A8%20Windows%20%E4%B8%8A%E8%AF%BB%E5%8F%96%E7%9A%84%E6%96%87%E4%BB%B6%E7%9A%84%E5%90%8D%E7%A7%B0%EF%BC%9F.png)
自从我开始使用 Linux 以来,一直让我感到困惑的一件事就是它允许你在读取文件时更改文件的名称,甚至删除它。一个例子是我在播放视频时意外尝试删除它。我成功了,并且让我感到惊讶的是,你可以更改文件中的几乎任何内容,而不必关心它是否正在被使用。
答案1
每当您在 Windows 中打开或执行文件时,Windows 都会将文件锁定在原地(这是一种简化,但通常确实如此)。被进程锁定的文件无法删除,直到该进程释放它。这就是为什么每当 Windows 需要更新时,您都需要重新启动才能使更新生效。
另一方面,Linux 和 Mac OS X 等类 Unix 操作系统不会锁定文件,而是锁定底层磁盘扇区。这似乎是一个微不足道的区别,但它意味着可以删除文件系统目录中的文件记录,而不会干扰任何已打开该文件的程序。因此,您可以在文件仍在执行或以其他方式使用时删除它,只要某个进程有它的打开句柄,它就会继续存在于磁盘上,即使文件表中的条目已消失。
答案2
Windows 默认为自动、强制文件锁定。UNIX 默认为手动、协作文件锁定。在这两种情况下,默认设置都可以被覆盖,但在这两种情况下通常都不能覆盖。
许多旧的 Windows 代码使用 C/C++ API(类似 的函数fopen
)而不是本机 API(类似 的函数CreateFile
)。C/C++ API 不允许您指定强制锁定的工作方式,因此您只能使用默认设置。默认的“共享模式”倾向于禁止“冲突”操作。如果您打开文件进行写入,则写入会被视为冲突,即使您从未实际写入该文件。重命名也是如此。
更糟糕的是,除了打开文件进行读取或写入之外,C/C++ API 没有提供任何方法来指定你打算对文件做什么。因此,API 必须假设你将执行任何合法操作。由于锁定是强制性的,open
因此允许冲突的操作将被拒绝,即使代码从未打算执行冲突的操作而只是为了其他目的打开文件。
因此,如果代码使用 C/C++ API,或者使用本机 API 而没有特别考虑这些问题,它们最终将阻止对打开的每个文件进行最大限度的可能操作,并且无法打开文件,除非打开后可以对文件执行的所有可能操作都没有冲突。
我认为,如果每个程序都明智地选择其共享模式和打开模式,并妥善处理故障情况,那么 Windows 方法的效果会比 UNIX 方法好得多。但是,如果代码不考虑这些问题,UNIX 方法的效果会更好。不幸的是,基本的 C/C++ API 无法很好地映射到 Windows 文件 API 上,无法很好地处理共享模式和冲突打开。因此最终结果有点混乱。
答案3
这是一个非常有趣的问题,它让我思考了一个可行的答案。我希望其他人可以在这里提供支持。
我使用 Windows 和 Linux,也注意到了这一点。我也是 vim 的用户。Vim 会将文本文件读入“缓冲区”或 RAM,然后在您保存之前不会触碰实际文件。Linux 可能通常会对所有文件执行此类操作。
以视频为例,它会将视频(如果可能的话)全部读取到 RAM 中,然后您就会获得一份可轻松访问、可搜索、可跳转的视频副本。如果文件太大,那么您可能会遇到问题,因为 Linux 可能不会读取整个视频,可能只会读取很大一部分。当您的播放器到达缓冲视频的末尾时,它会尝试再次读取文件。如果您删除了视频,那么这对您来说就很糟糕了。
在某些情况下,Windows 是一个“更安全”的操作系统,因为它不允许您这样做。它可能以与 Linux 相同的方式缓冲文件,但还会添加文件锁定,以防止您或其他程序更改您正在处理或查看的文件。这有助于保持文件完整,并防止您或其他程序覆盖彼此的更改。