我按照指定的顺序运行了以下命令:
$ln a b
$ls -i a b
523669 a 523669 b
$rm -f a
$ls -i b
523669 b
我从这个测试中得出结论,该命令rm
实际上仅删除文件名(a
在此测试中)而不是文件,因为 inode 仍然存在并且可以通过另一个文件名 ( b
) 检索。
我的问题是,如果一个文件仅硬链接到一个文件名,那么当rm
对该文件执行时,真实文件(即索引节点)是否被完全删除?如果没有,是否可以在没有文件名的情况下仅通过索引节点检索文件索引节点?
答案1
如果您尝试通过文件的索引节点打开文件,则会绕过任何目录遍历。目录遍历对于确定文件和指向该文件的目录的权限是必要的。如果没有目录遍历,内核就无法确定是否允许调用进程访问该文件。
有一个建议对 Linux 内核进行补丁,以允许从文件描述符创建到文件的链接。它是被拒绝,因为安全地实施这一点将非常困难。
在 Linux 下(可能出于同样的原因在其他 UNIX 变体上),您无法创建指向已删除文件的链接,因此如果文件不再有名称,您将无法重新添加名称。 1 您可以打开已删除的文件通过打开/proc/$pid/fd/
.
如果文件不再有任何链接并且不再打开,则它不再存在,并且其数据以前使用的空间可以随时回收。
1您可以通过以与文件系统相关的方式直接在文件系统中调整字节来实现此目的,例如使用debugfs
ext2/ext3/ext4。这需要访问安装了文件系统的设备(即通常只有 root 可以尝试它)。然而,虽然 debugfs 可以通过 inode 访问文件,但如果文件被删除,这并没有帮助:如果应用程序关闭文件,文件将被真正删除,并且在已安装的文件系统上以读写模式运行 debugfs 是一个秘方灾难。
答案2
自 20 世纪 70 年代初期以来,“ln”和“rm”命令在每个 UNIX 文件系统中的工作方式都与此完全相同。 Mac OSX、BSD 和 Linux 都继承了这个原始设计。
UNIX 文件本身没有名称,只有一个索引节点数字或整数。但是您只能通过特殊“目录”文件中的条目来访问它,该文件将名称与相关的 inum 相关联;您不能直接指定 inum 。
一个目录是本身一个文件,因此您还必须访问它通过(另一个)目录等等,通过一系列由正斜杠(/)分隔的目录名(称为“路径名”)。路径从进程的“当前工作目录”开始,除非名称以“/”开头,在这种情况下,路径从文件系统根目录开始。例如,如果路径名不包含“/”字符,则它应该是当前目录中的条目。
非目录文件可以有任意数量的路径名,称为“硬链接”,并且它将继续存在,直到全部其路径名已被删除和最后一个进程已关闭该文件。然后该文件实际上被删除,并且其空间被标记为可供重用。也就是说,您可以 creat() 或 open() 一个单链接文件,然后 unlink() 它,以便它不再出现在文件系统名称空间中,但该文件将继续存在,直到您关闭它。这对于不会被任何其他程序读取的临时暂存文件非常有用。
尽管目录有索引节点号,但大多数文件系统不允许对它们进行硬链接;它们只能出现在另一个目录中。 (一个不寻常的例外是 Mac OSX HFS+ 文件系统;这使得 Time Machine 备份可以工作。)您仍然可以创建目录(或任何其他文件)的“软链接”。软链接类似于目录条目,只不过它包含另一个路径名而不是 inum。
每个 UNIX 文件都有所有者、组和访问权限。它们允许您打开文件是必要的,但还不够;您还必须至少对用于引用它的路径名中的每个目录具有执行权限。这就是为什么没有标准方法可以通过索引节点号打开 UNIX 文件。这将绕过一个重要的、广泛使用的安全机制。
但这并不能解释为什么不能有一个标准的方法根(特权)用户通过索引节点号打开文件,因为无论如何都会绕过权限检查。这对于某些系统管理功能(例如备份)非常有用。据我所知,这样的机制确实存在,但它们都是特定于文件系统的;对于任何 UNIX 文件系统都没有通用的方法。
答案3
在 Linux 上,debugfs
,交互式 ext2/ext3/ext4 文件系统调试器提供了一个ln
命令,可以将 inode 号作为filespec
并创建到相应文件的新硬链接。但在实践中,这需要未链接的文件由进程保持打开状态,在 中维护一个打开的文件描述符/proc/[pid]/fd/[n]
。尝试对已删除的文件执行此操作很可能会导致文件系统损坏。
这是因为为了确保 ext3(以及扩展 ext4)可以在崩溃后安全地恢复取消链接,它实际上将 inode 中的块指针清零,而 ext2 只是在块位图中将这些块标记为未使用,并将 inode 标记为“已删除”,并保留块指针。即便如此,由于需要以读写方式安装文件系统才能创建硬链接,因此为已删除文件保留的块可能已经被重新分配。
在内核版本 2.6.39 之前,它曾经是ln
-L|--logical
GNU coreutils 中引入的选项v8.0可用于通过打开的文件描述符恢复未链接的文件/proc/[pid]/fd/[n]
如果未链接的文件和新的硬链接都驻留在临时文件系统文件系统 。此功能从此被残疾人, 由于, 由于吉尔斯指出,允许直接从文件描述符创建硬链接涉及安全考虑。