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

Thu*_*ing 3 linux file-io

我碰到了这个问题,这个关于在Linux中删除打开的文件的问题

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

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

  • 当进程打开文件时,将在UFDT中为该文件创建一个新条目。
  • 当进程删除文件时,到该文件的所有链接都消失了,尤其是我们没有对其的引用inode,因此,该文件已从GFDT中删除。
  • 但是,在修改文件时(例如写入文件),必须在磁盘中进行更新(因为其页面已修改/脏了),但是由于删除的较早,它在GFDT中没有引用,所以我们不知道inode对此。

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

编辑通过UFDT我的意思是保持其打开的过程的文件的文件描述符进程的文件描述符表(每个进程都有自己的UFDT)和GFDT是全球文件描述符表,只有一个GFDT在系统(本例中为RAM)。

Fil*_*ves 6

我从未真正听说过那些UFDT和GFDT的缩写词,但是您对系统的看法听起来似乎是正确的。我认为您对内核如何管理打开文件的描述缺少一些细节,也许这就是您困惑的地方。我将尝试给出更详细的描述。

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

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

删除文件包括调用unlink(2)。此功能从目录取消链接文件。磁盘中的每个文件索引节点都有指向它的链接数;仅当链接计数达到0且未打开时才真正删除该文件(对于目录,则为2,因为目录引用其自身并且也由其父级引用)。实际上,unlink(2)有关此行为的手册非常具体:

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

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

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

但是文件仍然存在。它只是没有出现在任何目录条目中。

例如,如果文件很大,并且运行dfdu,则会看到空间使用情况相同。该文件仍在磁盘上,您无法访问。

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

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