删除目录时出现“ls”错误

删除目录时出现“ls”错误

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

ls: cannot open directory .: Stale file handle

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

答案1

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

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

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

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

mkdir one two
touch one/1 two/2
cd one
ls

在另一个外壳中:

mv one tmp
mv two one
mv tmp two

在第一个外壳中:

ls

该文件1位于最初名为 的目录中one,现在名为two.该文件2位于最初名为 的目录中two,现在名为one.

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

答案2

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

答案3

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

答案4

一个目录,就像一个文件,有一个与之关联的索引节点:

307 % mkdir ABC

308% ls-i 11997708A 11997709 B 11997710 C

索引节点是包含有关目录或文件信息的数据结构。每个目录和文件都有一个。将其视为一个地址(实际上是一个索引号)。

如果我在A,inode号11997708并在另一个 shell 中(或在与我要做的相同的 shell 中)删除目录 A,然后重新创建它并 ls 索引节点:

309% cd A

310% rmdir ../A

311% mkdir ../A

312% ls -i ..

11997720A 11997709 B 11997710 C

i节点不同,因此如果它尝试在已删除的目录A中创建文件:

313% 接触过这个

触摸:无法触摸“此”:没有这样的文件或目录

因为我所在的目录 - 不再与 inode 关联11997720 - 所以我现在所在的位置不再有合法的地址/索引 - inode。因此出现错误。

相关内容