如果删除工作目录实际会发生什么,内核如何处理?

What does actually happens if you delete the working directory, how the kernel handles that?

我试图在整个 SO 中找到这个答案,但没有找到。先举个例子:

$ cd /tmp
$ mkdir foo
$ cd foo
$ pwd
/tmp/foo
$ $SHELL
$ rmdir /tmp/foo
$ exit
$ pwd
/tmp/foo
$ ls
<no output>
$ man ls
man: can't change directory to '': No such file or directory
man: command exited with status 255: (cd  && LESS=-ix8RmPm Manual page ls(1) ?ltline %lt?L/%L.:byte %bB?s/%s..?e (END):?pB %pB\%.. (press h for help or q to quit)$PM Manual page ls(1) ?ltline %lt?L/%L.:byte %bB?s/%s..?e (END):?pB %pB\%.. (press h for help or q to quit)$ MAN_PN=ls(1) pager -s)
$ echo -e '#include<unistd.h>\n#include<stdio.h>\n#include<stdlib.h>\nint main(){char*p=getcwd(NULL,0);printf("%s\n",p);free(p);}' | gcc -x c -
/usr/bin/ld: cannot open output file a.out: No such file or directory
collect2: error: ld returned 1 exit status
$ cd $PWD
cd: no such file or directory: /tmp/foo

这里内部发生了什么?内核如何处理这种情况?如果假设当前目录仍然是一个文件描述符,为什么所有这些命令都失败了?

而且,(至少对我而言)更重要的是,为什么 没有 保护措施来防范此类问题?在我看来,它很容易导致严重的安全问题...

删除目录时,将执行以下步骤:

  • 其父目录中的 link 已删除
  • 其父目录中的..link被删除
  • 删除目录中的. link

当其中每一个发生时,目录的 link 计数将被删除。当 link 计数变为 0 时,目录本身将从文件系统中删除。

如果有任何进程访问目录(作为工作目录,或者因为它们调用了 opendir()),这些也会增加目录的 link 计数。因此,在所有这些访问都消失之前,目录并没有真正消失。

当目录处于此状态时,可以读取它,但是任何依赖于上述任何 link 的内容都将失败。当您执行 cd $PWD 时,它正在尝试执行 cd /tmp/foo,但 foo link 已被删除。