删除目录时出现`ls`错误

fon*_*ini 13 filesystems bash open-files pwd

我打开了两个贝壳。第一个在目录 A 中。在第二个中,我删除目录 A,然后重新创建它。当我回到第一个 shell 并键入 时ls,输出为:

ls: cannot open directory .: Stale file handle
Run Code Online (Sandbox Code Playgroud)

为什么?我认为第一个 shell(在不存在的目录中保持打开状态的 shell)会在等待下一个命令时“冻结”,并且不会“意识到”该目录已被删除并重新创建。除了字符串之外,shell 是否持有对其当前工作目录的“更深层次”引用$PWD

Gil*_*il' 17

目录(如任何文件)不是由其名称定义的。将名称视为目录的地址。当你移动目录时,它仍然是同一个目录,就像你搬到不同的房子,你仍然是同一个人。如果你删除一个目录并创建一个同名的新目录,它就是一个新目录,就像搬进你以前住的房子的人不是你一样。

每个进程都有一个工作目录cdshell 中的命令会更改 shell 的当前工作目录。该pwd命令打印当前工作目录的¹路径。

当您删除目录 A 时,这样做是删除其父目录中 A 的条目。目录 A 本身保留在文件系统中,但处于分离状态,没有名称。它还没有被删除,因为它正在被一个进程使用,即第一个 shell。当您在第一个 shell 中更改目录时,该目录最终被删除。当一个文件被删除而进程仍然打开它时,同样的事情会发生:文件的目录条目被立即删除,并且文件本身在它停止使用时被删除。

同样,观察移动目录时会发生什么。

mkdir one two
touch one/1 two/2
cd one
ls
Run Code Online (Sandbox Code Playgroud)

在另一个外壳中:

mv one tmp
mv two one
mv tmp two
Run Code Online (Sandbox Code Playgroud)

在第一个外壳中:

ls
Run Code Online (Sandbox Code Playgroud)

该文件1位于最初调用one和现在调用的目录中two。该文件2位于最初调用two和现在调用的目录中one

¹更准确地说,一条路径,如果涉及符号链接或其他微妙之处,则路径可能不是唯一的。

  • @Nacht 当前目录不是文件描述符,但它的工作原理很像。内核为每个进程维护它。在 Linux 上,你可以在 `/proc/<pid>/cwd` 中看到它,它的工作原理类似于 `/proc/<pid>/fd/<number>`。它是 `lsof` 的输出中的 `CWD`。 (2认同)

tal*_*zin 8

新目录A与目录A不同,stat删除旧目录前和新建目录后用命令查看,会看到不同的i-node编号。
我认为这与内核的工作方式有关。它只是跟踪每个进程的当前目录的 i-number。因此,由于有不同的 i 编号,这将导致不同的冲突。

  • 这不是删除你的理由!如果你有这种感觉,你可以在你的答案中添加一个免责声明,说明你认为另一个更好。 (6认同)

Joh*_*ohn 7

这是预期的行为。新目录 A 与旧目录 A 不同,它恰好具有相同的名称。所以第一个终端的 $PWD 仍然消失了,当你执行mkdir A.

  • 您能否详细说明“新目录 A 与旧目录 A 不同”。文件/目录的哪些方面发生了变化?它与inode编号有关吗?很抱歉问,但我只是在学习这个。 (2认同)
  • @rahul 从哲学上讲,改变的是它的 *identity*——在同一位置从无到有创建了一个新目录。在实现级别,是的,所有打开的文件都由 inode 标识,并且旧目录和新目录将具有不同 inode 编号的不同 inode。 (2认同)