Linux 如何管理删除临时文件?

How does Linux manage deleting temporary files?

我一直在研究一些 Linux 实现,我想到了一个问题。

据我所知,有一个位将文件标记为临时文件。当生成该文件的进程死亡时,内核如何删除它?我认为它可能与文件描述符 table 有关,但我不确定。

如果有人能一步一步地解释一下,那会派上用场的!

没有将文件标记为临时文件的位。

每个 inode 都有一个 link count 字段,这是引用该文件的目录条目数。每次对文件进行硬 link 时,此计数都会增加,而当您删除名称时,此计数会减少;当计数归零时,文件被删除(inode 被标记为可用,所有数据块被放入空闲列表)。

当一个文件在进程中打开时,inode 的副本保存在内核的文件中 table,并且引用它的文件句柄的数量被添加到 link计入这个副本。当进程关闭其文件描述符时,link 计数会减少。直到这个内存中的 link 计数降为零,文件才真正被删除。这就是文件在打开时保留在磁盘上的原因,即使所有名称都被删除。

因此当您创建一个临时文件时,它会执行以下步骤:

  1. 创建文件。磁盘 inode link count = 1.
  2. 打开文件。内核inode link count = 2.
  3. 删除文件名。内核inode link count = 1.

此时,进程可以继续使用临时文件,但由于没有名字,其他进程无法打开。

当进程关闭文件句柄时,link 计数变为 0,文件被删除。

最近版本的 Linux 有一个 O_TMPFILE 标志 open(2) 可以自动执行此操作。您无需指定文件名,而只需指定目录,该目录仅用于查找文件系统来保存文件数据。使用它时,它会在一次调用中有效地完成上述所有 3 个步骤,但它实际上不会在任何地方创建文件名(因此避免了竞争条件和名称冲突)。

我一直在研究这个主题,并且发现了一些额外的信息来补充 Barmar 提供的答案。

我阅读了有关 tmpfile() 系统调用的内容。这个系统调用创建一个临时文件和 returns 一个流描述符。

问题是 tmpfile 在内部调用了 unlink。从而减少 link 计数。尽管此 link 是最后一个文件,但如果文件已被任何进程打开,它将一直存在直到关闭。我不是 100% 确定这个过程在内部是如何工作的,但我认为这是由于 iPut 算法验证引用计数和 link 计数的顺序。我看过 iPut 的一些实现,首先,它检查引用计数是否为零,如果是,则转到 link 计数,如果它等于零,则释放分配给文件的所有块.

所以在这种情况下,我们会有引用计数==1,因为我们仍然有一个打开文件的进程,但 link 计数将为零。所以在进程关闭文件之前,iput 不会释放 i-node。