-d, -F, --directory
allow the superuser to attempt to hard link directories (note:
will probably fail due to system restrictions, even for the su‐
peruser)
可能让大多数人感到困惑的部分是挂载点。如果您将磁盘安装为/mnt/foo,则cd /mnt/foo; ls -ld ..指向安装点的索引节点,在本例中为 的索引节点/mnt。挂载目录的硬链接并..没有真正跨越文件系统边界,因为它只是查看 /mnt/foo 的硬链接(无论当前是否安装了一个卷,它都存在)或者它被特殊处理内核支持挂载的卷。这很可能是一个实现细节,我无法指出任何与之相关的内核源代码,但从功能上讲,它在技术上仍然是一个硬链接,因为它..指向一个索引节点,而不是一个指向文件名的软链接。
您可以使用以下方法自行测试:
cd /
stat .
stat ..
在 Linux 和 macOS 上,当使用-x标志调用时,您会看到两者.都..指向 inode 2。许多文件系统为坏块保留 inode 1。
这取决于文件系统。大多数文件系统遵循传统的 Unix 设计,其中
.
和..
是硬链接。目录的硬链接数是 2 + n,其中 n 是子目录的数量:即目录父目录中的条目、目录自己的条目.
以及每个子目录的..
条目。每次创建、删除或移入或移出目录时,都会更新硬链接计数。请参阅为什么新目录在添加任何内容之前的硬链接数为 2?以获得更详细的解释。一些文件系统偏离了这一传统,特别是btrfs。
这是不准确的措辞。更准确地说,您不能使用
ln
实用程序或link
系统调用或类似方法创建到目录的硬链接,因为内核会阻止您。调用mkdir
确实会创建到新目录父目录的硬链接。这是在文件系统上创建到目录的新硬链接的唯一方法(相反,删除目录是删除到目录的硬链接的唯一方法)。另外,请注意,将硬链接视为“指向”主文件是一种误导。与符号链接不同,硬链接不是定向的。当一个文件有多个硬链接时,它们是等价的。在以下顺序之后:
文件系统中没有任何东西
b/file
次于a/file
. 这两个目录条目都引用同一个文件。它们都是文件的硬链接。这是一个实现细节。
在符合 POSIX 的文件系统中,
..
充当硬链接。然而,一些文件系统只是模拟它,并不实际将它存储在磁盘上。
出于功能目的,假设您没有文件系统损坏,区别是没有意义的。(如果这样做,fsck 旨在解决此问题。)
非 posix 完全模拟硬链接的失败之一是硬链接计数未指示目录内子目录的正确数量。
find
option选项-noleaf
禁用使用此链接计数的优化。作为吉尔斯回答的补充,我认为值得关注这些词并对其进行扩展:
理解 linux 中文件的概念模型非常重要,其中目录中的每个名称都是指向可能指向数据的“inode”的“链接”。
这里令人困惑的是“硬链接”和“符号链接”的命名约定听起来像是同一事物的两种风格。他们不是!
一个常规文件是:
“硬链接文件”也不例外:
但是符号链接是:
那么为什么不能硬链接目录呢?
我得到的最好的解释来自于这个。该
..
条目必须在目录中维护。如果您有多个指向目录本身的名称,那么您可能有多个父级,这是不可能的,因为..
只能存在一次,就像每个其他可能的名称在目录中只能存在一次一样。.
并且..
是指向 inode 的特殊硬链接从纯粹实用主义的角度来看,
..
是一个硬链接。在 Linux 上,当从挂载卷的顶层调用时,它被视为挂载点的硬链接,在 Linux 和 macOS 上,/
硬链接.
和..
inode 2 作为一种特殊情况。更多详情
正如其他人指出的那样,
.
和..
都是支持 inode 的文件系统上 inode 的硬链接。有一些文件系统没有索引节点,但这是一个附带问题。出于实际目的,无论系统是否直接支持索引节点,硬链接都只是指向给定文件系统上的相同元数据块。有时硬链接是文件系统上的真实链接,有时它是合成的,因为 POSIX 系统期望.
并且..
由于历史原因而存在。无论哪种方式,它都被视为到目录的硬链接,并且某些文件系统(例如 HFS+)确实允许您硬链接不跨越文件系统边界的目录。目录的硬链接
MacOS确实允许 HFS+ 文件系统上的硬链接指向目录,因为这在历史上是 Time Machine 优化磁盘使用的方式。但是,较新版本的 Time Machine 使用 APFS 文件系统和文件系统快照,因此除了向后兼容性外,实际上不需要此例外,并且它不适用于 APFS。不要依赖它。
因此,通常是文件系统本身决定目录是否可以硬链接。在 Ubuntu 22.04 上,如果系统允许,ln
man 1 ln
实用程序支持目录链接:可能让大多数人感到困惑的部分是挂载点。如果您将磁盘安装为
/mnt/foo
,则cd /mnt/foo; ls -ld ..
指向安装点的索引节点,在本例中为 的索引节点/mnt
。挂载目录的硬链接并..
没有真正跨越文件系统边界,因为它只是查看 /mnt/foo 的硬链接(无论当前是否安装了一个卷,它都存在)或者它被特殊处理内核支持挂载的卷。这很可能是一个实现细节,我无法指出任何与之相关的内核源代码,但从功能上讲,它在技术上仍然是一个硬链接,因为它..
指向一个索引节点,而不是一个指向文件名的软链接。您可以使用以下方法自行测试:
在 Linux 和 macOS 上,当使用
-x
标志调用时,您会看到两者.
都..
指向 inode 2。许多文件系统为坏块保留 inode 1。由于您可以在某些文件系统上创建指向目录的硬链接,包括带有debugfs的 EXT3/4 ,因此您不能硬链接目录并不是真的。通常不支持它以确保目录图是非循环的,并且像fsck这样的工具会抱怨除当前工作目录 ( ) 和父目录之外的
.
任何..
文件系统不支持目录硬链接的文件系统之外的硬链接目录.
目录 (..
) 作为一个特殊的遗留案例。