在linux中删除打开的文件时内部会发生什么

时间:2015-06-28 11:39:01

标签: linux file-io

我遇到了关于删除linux中已打开文件的thisthis个问题

但是,当进程(称为A)删除另一个进程B打开的文件时,我仍然对RAM中发生的事情感到困惑。

令我感到困惑的是这个(我的分析可能是错的,如果是这样,请纠正我):

  • 当进程打开文件时,会在UFDT中创建该文件的新条目。
  • 当进程删除文件时,该文件的所有链接都将消失 特别是,我们没有引用它的inode,因此,它将从GFDT中删除
  • 但是,在修改文件时(比如写入文件),必须在磁盘中更新(因为它的页面被修改/变脏),但由于早期的删除,它在GFDT中没有引用,所以我们不知道知道它的inode

问题为什么“已删除”文件仍可由打开它的进程访问? 操作系统是如何完成的?

编辑 UFDT 我指的是进程的文件描述符表,其中包含由进程打开的文件的文件描述符(每个进程都有自己的UFDT)并且 GFDT 是全局文件描述符表,系统中只有一个GFDT(在我们的例子中是RAM)。

2 个答案:

答案 0 :(得分:5)

我从来没有真正听说过那些UFDT和GFDT缩略词,但你对系统的看法听起来大多是正确的。我认为你缺乏关于内核如何管理打开文件的描述的一些细节,也许这就是你的困惑所在。我将尝试提供更详细的说明。

首先,有三种数据结构用于跟踪和管理打开的文件:

  • 每个进程都有一个文件描述符表。此表中的每个条目都存储文件描述符和文件描述符状态标志(截至目前,唯一的标志是O_CLOEXEC)。文件描述符只是指向文件表条目中的条目的指针,我将在下面介绍。 open(2)和family返回的整数通常是此文件描述符表的索引 - 每个进程都有其表,这就是为什么open(2)和family可以为不同的进程返回相同的值文件。
  • 整个系统中有一个打开的文件表。每个进程的每个文件描述符表条目引用打开的文件表中的这些条目之一。每个打开的文件在此表中有一个条目:如果两个进程打开同一个文件,则创建此全局表中的两个条目,即使它是同一个文件。 files表中的每个条目都存储文件状态标志(打开以供读取,写入,追加等)和当前文件偏移量。这就是为什么不同的进程可以同时读取和写入同一文件中的不同偏移量,只要它们每个都打开文件。
  • 文件表条目中的每个条目也引用vnode表中的条目。 vnode表是一个全局表,每个唯一文件都有一个条目。如果进程A,B和C打开文件D,则只有一个vnode表条目,由所有3个文件表条目引用(在Linux中,实际上没有vnode,而是有一个inode,但是让#39 ; s保持此描述的通用性和概念性)。 vnode条目包含与传统inode(文件大小,其他属性等)几乎相同的信息,但它还包含对打开的文件有用的其他信息,例如活动的文件锁,谁拥有它们,哪些部分他们锁定的文件等等。这个vnode条目还存储指向磁盘上文件数据块的指针。

删除文件包括调用unlink(2)。此函数取消链接文件与目录。磁盘中的每个文件inode都有一个指向它的链接数量;如果链接计数达到0并且未打开(或者在目录的情况下为2,因为目录引用自身并且也由其父引用),则仅真正删除该文件。实际上,unlink(2)的联机帮助页对此行为非常具体:

  

取消链接 - 删除名称及其引用的文件

因此,不要将取消链接视为删除文件,而是将其视为删除文件名,以及它所引用的文件。

unlink(2)检测到存在引用此文件的活动vnode表条目时,它不会从文件系统中删除该文件。什么都没发生。是的,您无法在文件系统上找到该文件。 find(1)无法找到它。您无法在新流程中打开它。

但文件仍在那里。它不会出现在任何目录条目中。

例如,如果它是一个巨大的文件,并且如果您运行dfdu,您将看到空间使用情况相同。该文件仍然存在,在磁盘上,您无法访问它。

因此,任何读取或写入都会照常进行 - 文件数据块可通过vnode表条目访问。您仍然可以知道文件大小。和主人。和权限。所有的。一切都在那里。

当进程终止或显式关闭文件时,操作系统会检查inode。如果指向inode的链接数为0,并且这是打开文件的最后一个进程(也通过在vnode表条目中存储链接计数来指示),则清除该文件。

答案 1 :(得分:0)

  

当进程打开文件时,UFDT中该文件的新条目是   创建

这个奇怪的缩写是什么?我认为你的意思是有问题的过程有一个文件描述符。

  

当进程删除文件时,该文件的所有链接都将消失   特别是,我们没有引用它的inode,因此它被删除了   来自GFDT

GFDT究竟是什么?

  

但是,在修改文件(比如写入文件)时,必须更新文件   在磁盘中(因为它的页面被修改/变脏),但它没有   由于早期的删除,GFDT中的引用,所以我们不知道   它的inode。

我猜这个GFDT与“全局”和“文件描述符”有什么关系。

所以,所有这些都表明了严重的误解。

正如您自己的问题所述,该文件与名称不同。接下来,当您从文件系统打开某些内容时,它会获得inode的内存中表示,并分配 struct file 对象,该对象稍后指向内存中的inode。最后,更新相关线程的文件描述符表以将指针存储到给定偏移处的 struct file 对象。偏移量称为文件描述符。

那么。与inode关联的名称数量与内核发出影响inode的读/写(或阻止它所代表的文件)的能力无关,只要它在删除姓氏之前打开它。

当没有名称且内核不再使用它时,可能会或可能不会被删除。