Linux 似乎并不介意我移动或删除进程仍在使用的文件或目录。那么,如果我尝试卸载进程正在用作工作目录的设备,为什么它会抱怨呢?
例子:
$ mkdir -p a b
$ sudo mount --bind a b
$ sh -c 'cd b; sleep 10' &
[1] 215679
$ sudo umount b
umount: /home/laktak/b: target is busy.
$
[1]+ Done sh -c 'cd b; sleep 10'
$ sudo umount b
$
相对于:
$ mkdir c
$ sh -c 'cd c; sleep 10; pwd; cd ..' &
[1] 220382
$ rmdir c
$
$ pwd: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
chdir: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
$
[1]+ Done sh -c 'cd c; sleep 10; pwd; cd ..'
答案1
这里有一个明显的区别:在 ext2/3/4 文件系统上,通过文件名“删除”文件意味着对 inode 的引用,即文件数据附加到的数据结构,被删除(您删除的文件名)。 see inls
只是对该 inode 的引用)。仅当最后一个此类引用消失时,文件才被视为“已删除”(如果您有兴趣,可以研究“硬链接”的概念)。但是,如果您打开一个文件,该操作还会创建对该 inode 的引用,因此只要该文件打开,它实际上就不会被“删除”,并且打开该文件的进程仍然可以使用该文件。
对于开放目录也是如此。只要您仍在cd
该目录中,即使您从另一个 shell 实例中删除了该目录,该目录仍然存在。然而,它已经处于“降级”状态,无法再从其他进程访问,并且即使从仍然存在的 shell 实例也无法在该目录中创建新文件。 (顺便注意,我无法重现您在第二个示例中显示的行为:当我在bash
4.3 中运行相同的代码时,pwd
即使从主 shell 实例中删除目录名称,也能正确打印目录名称)。
另一方面,卸载设备用于切断与所包含文件的所有连接,并刷新所做的所有更改,因此当有人仍然“在那里”时,操作系统将拒绝这样做。