【问题标题】:What happens internally when deleting an opened file in linux在 linux 中删除打开的文件时内部会发生什么
【发布时间】:2015-09-14 22:51:18
【问题描述】:

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

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

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

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

问题是为什么打开它的进程仍然可以访问“已删除”文件? 以及操作系统是如何做到这一点的?

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

【问题讨论】:

    标签: linux file-io


    【解决方案1】:

    我从未真正听说过那些 UFDT 和 GFDT 的首字母缩略词,但您对系统的看法听起来基本正确。我认为您对内核如何管理打开的文件的描述缺乏一些细节,也许这就是您的困惑所在。我会尽量给出更详细的描述。

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

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

    删除文件包括调用unlink(2)。此函数从目录中取消链接文件。磁盘中的每个文件 inode 都有指向它的链接数的计数;仅当链接计数达到 0 且未打开文件时才真正删除该文件(或者在目录的情况下为 2,因为目录引用自身并且也被其父级引用)。事实上,unlink(2) 的手册页对这种行为非常具体:

    取消链接 - 删除一个名称,可能还有它所指的文件

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

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      GFDT 到底是什么?

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

      我猜无论这个 GFDT 是什么,都与“全局”和“文件描述符”有关。

      因此,所有这些都表明存在严重的误解。

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

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

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

      【讨论】:

      • 我编辑了关于 GFDT 和 UFDT 的含义的问题。那么该结构文件对象仅对一个进程来说是独一无二的吗?我的意思是,当一个进程关闭结构文件时,无论文件是否被删除,它都会从其(进程)内存空间中删除?同样,如果文件被删除,结构文件不会受到影响?
      猜你喜欢
      • 1970-01-01
      • 2011-01-02
      • 2021-05-02
      • 1970-01-01
      • 2020-07-18
      • 2014-02-07
      • 1970-01-01
      • 1970-01-01
      • 2019-12-18
      相关资源
      最近更新 更多