我有两个壳打开。第一个位于目录 A 中。在第二个中,我删除目录 A,然后重新创建它。当我返回第一个 shell 并输入 时ls
,输出为:
ls: cannot open directory .: Stale file handle
为什么?我认为第一个 shell(在不存在的目录中保持打开状态的 shell)会在等待下一个命令时“冻结”,并且不会“意识到”该目录已被删除并重新创建。除了字符串之外,shell 是否还拥有对其当前工作目录的“更深”引用$PWD
?
答案1
目录(像任何文件一样)不是由其名称定义的。将名称视为目录的名称地址。当你移动目录时,它仍然是同一个目录,就像你搬到不同的房子,你仍然是同一个人一样。如果您删除一个目录并创建一个同名的新目录,那么它就是一个新目录,就像搬进您以前居住的房子的人不是您一样。
每个进程都有一个工作目录。cd
shell 中的命令更改 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。因此出现错误。