我刚刚将日志文件重命名为“foo.log.old”,并假设应用程序将开始在“foo.log”处写入新的日志文件。我惊讶地发现它跟踪日志文件到它的新名称,并不断向“foo.log.old”追加行。
在 Windows 中,我不熟悉这种行为 - 我不知道是否可以实现它。这种行为在 Linux 中到底是如何实现的?我可以在哪里了解更多相关信息?
答案1
程序通过文件系统维护的编号(在传统 UNIX 文件系统上称为 inode)连接到文件,名称只是一个引用(并且可能不是唯一的引用)。
所以需要注意以下几点:
- 使用 移动文件
mv
不会更改该下属编号,除非您跨文件系统移动它(这相当于在原始文件系统上使用cp
then )。rm
- 因为多个名称可以连接到一个文件(即我们有硬链接),所以“已删除”文件中的数据不会消失,直到全部对底层文件的引用消失。
- 也许最重要的是:当程序
open
访问文件时,它会引用该文件(为了删除数据的目的),相当于将文件名连接到该文件。
这会导致以下几种行为:
- 程序可以
open
读取文件,但直到用户rm
在命令行编辑它之后才真正读取它,并且程序仍然可以访问数据。 - 您遇到的情况是:
mv
ing 文件并不会断开该文件与打开该文件的任何程序之间的关系(除非您跨越文件系统边界,在这种情况下,程序仍然可以使用原始版本)。 - 如果一个程序已经
open
编辑了一个要写入的文件,并且用户rm
在命令行中输入了最后一个文件名,则该程序可以继续将内容放入文件中,但是一旦它关闭,就不会再引用该数据,并且它会消失。 - 通过一个或多个文件进行通信的两个程序可以通过在完成后删除文件来获得粗略的部分安全性
open
。 (这不是实际的安全意识,它只是将一个漏洞转变为一个竞争条件。)
答案2
要真正了解这种行为是如何实现的,您可以查看一些 Unix 编程书籍。 Mathepic 是正确的,因为它与 inode 相关。实际的路径名仅用于打开文件,一旦完成,程序将通过其打开的文件描述符引用它。文件描述符依次引用索引节点,在这种情况下,索引节点不关心底层文件名是否已更改。
至于在 Windows 中实现这一点,这是另一个站点的问题。
要在不阅读书籍的情况下阅读更多相关内容,只需搜索 linux 文件系统和索引节点即可。可能没有明确的答案,但您将能够理解原因。