为什么 /proc/$PID/fd/ 中的符号链接充当硬链接?

为什么 /proc/$PID/fd/ 中的符号链接充当硬链接?

当符号链接的目标被删除时,它将指向虚无,并且无法获取已删除目标的内容。

中的文件/proc/$PID/fd/显示为符号链接,但它们允许您获取已删除目标的内容,如下所述:使用以下工具恢复已删除的 Linux 文件lsof

这是如何工作的?如果它不充当符号链接,为什么会显示为符号链接?它是 proc 文件系统的符号链接实现,保留对文件 inode 的引用吗?

答案1

如果其目标被删除,则当您使用或 时, 中的实体/proc/$PID/fd/将显示为损坏的符号链接,但使用 打开时其行为确实会有所不同。ls(1)file(1)open(2)

在我的 Debian 9 上,我曾经strace(1)尝试查看读取符号链接时会发生什么。命令是sudo strace cat "$symlink"。stderr 中的相关行是

  • 都可以

    open("$symlink", O_RDONLY)                   = 3
    
  • 或者ENOENT

    open("$symlink", O_RDONLY)                   = -1 ENOENT (No such file or directory)
    

(注意:我并不是说这些都是open(2)一般可能的结果)。

结果:

               | regular symlink | /proc/$PID/fd/$N |
---------------+-----------------+------------------+
exists, valid  |       OK        |        OK        |
exists, broken |     ENOENT      |        OK        | <- the difference
doesn't exist  |     ENOENT      |      ENOENT      |
---------------+-----------------+------------------+

我还了解到,当我运行 时,file "$symlink"它会调用和。这些是基于路径而不是文件描述符的系统调用。如果符号链接存在(有效或损坏),则永远不会调用 来打开它或其目标。from表示链接已损坏。lstat(2)readlink(2)stat(2)open(2)ENOENTstat(2)

我的结论是:“断开的链接”是从某些系统调用的输出派生出的属性;但是当你从 打开一个链接时/proc/$PID/fd/open(2)只知道如何处理它,而不关心其他工具会产生什么结果。

请注意,整个过程/proc仅伪造了一个“正常”的文件系统。有几个怪癖:

  • 文件可能具有动态内容,但它们不会被系统调用修改(尝试inotifywait)。
  • 对象可能会出现(消失),但它们并没有被系统调用创建或删除(再次inotifywait)。
  • 从某种意义上说,对象可能在你与它们交互之前不存在。运行bash并等待几分钟。调用ls -l /proc/$$/fd以查看其文件描述符。ctimes 可能会显示“此时此刻”。但是,如果你每隔几秒钟重复该命令,你会注意到 ctimes 永远不会改变。(琐事:起初我以为我可以回答这个问题确定文件已打开的时间stat符号链接/proc/$PID/fd/但是我错了;现在你知道为什么了)。

难怪您询问的这些符号链接在某些情况下不像常规符号链接那样工作。整个/proc设计的行为略有不同。我想是open(2)故意赋予了利用它的能力。

相关内容