为什么会存在硬链接?

Luc*_*c M 89 filesystems hard-link

我知道什么是硬链接,但我为什么要使用它们?硬链接有什么用?

War*_*ung 65

硬链接的主要优点是,与软链接相比,没有大小或速度损失。软链接是在正常文件访问之上的额外间接层;当您打开文件时,内核必须取消对链接的引用,这需要一些时间。该链接还占用磁盘上的少量空间,用于保存链接的文本。硬链接不存在这些惩罚,因为它们内置于文件系统的结构中。

我所知道的最好的方式是:

$ ls -id .
1069765 ./
$ mkdir tmp ; cd tmp
$ ls -id ..
1069765 ../
Run Code Online (Sandbox Code Playgroud)

使它的-i选项为ls您提供文件的inode 编号。在我准备上面例子的系统上,我碰巧在一个inode号为1069765的目录中,但是具体的值并不重要。它只是标识特定文件/目录的唯一值。

这意味着当我们进入一个子目录并查看名为的不同文件系统条目时..,它具有与我们之前获得的相同 inode 编号。这不会发生,因为 shell 正在..为您解释,就像 MS-DOS 和 Windows 那样。在 Unix 文件系统上..是一个真正的目录条目;它是一个指向前一个目录的硬链接。

硬链接是将文件系统的目录联系在一起的筋。曾几何时,Unix 没有硬链接。添加它们是为了将 Unix 的原始平面文件系统转变为分层文件系统。

(有关这方面的更多信息,请参阅为什么 '/' 有一个 '..' 条目?。)

在 Unix 系统上,几个不同的命令由同一个可执行文件实现也是很常见的。在 Linux 上似乎不再是这种情况,但在我过去使用的系统上cpmvrm都是相同的可执行文件。如果您考虑一下,这是有道理的:当您在卷之间移动文件时,它实际上是先复制后删除,因此mv必须实现其他两个命令的功能。可执行文件可以确定要提供哪个操作,因为它传递了调用它的名称。

另一个在嵌入式 Linux 中很常见的例子是BusyBox,它是一个可执行数十个命令的可执行文件。

我应该指出,在大多数文件系统上,不允许用户对目录进行硬链接。的...条目自动地由文件系统代码,通常是内核的一部分进行管理。之所以存在这种限制,是因为如果您不小心创建和使用目录硬链接的方式,可能会导致严重的文件系统问题。这是存在软链接的众多原因之一;他们不承担同样的风险。

  • 关于“链接还占用磁盘上的少量空间,以保存链接的文本。” 在现代文件系统上,没有额外的空间用于存储链接路径,因为目录条目本身用于存储它,至少在名称不太长的情况下是这样。这称为“快速符号链接” (5认同)
  • 此外,如果您删除符号链接的目标,文件就会消失并且符号链接会损坏。硬链接不存在的问题。 (4认同)
  • 但是硬链接也有一些信息——它们的名字。所以它应该占用空间。 (2认同)

hmo*_*liu 40

硬链接的一种非常有用的用法是与 rsync 相结合的增量备份。它节省了大量空间,并使恢复过程非常容易。我使用这种方法在我的服务器中进行备份。

花一些时间阅读此说明


bah*_*mat 12

如果在阅读该维基百科页面后,您的问题是“我为什么要使用它们”,那么您不明白什么是硬链接。

一个链接是一个目录条目指向的磁盘块。换句话说,您系统上的每个文件都至少有一个链接。当你创建rm一个文件时,实际的系统调用是unlink(). 它删除目录条目。磁盘上的块没有改变,但链接消失了,因此文件从目录列表中消失了。

您个人可能永远不会使用硬链接,但它们遍布您的系统。例如:

$ ls -li /bin | grep 53119771
53119771 -rwxr-xr-x 3 root root  26292 2010-08-18 10:15 bunzip2
53119771 -rwxr-xr-x 3 root root  26292 2010-08-18 10:15 bzcat
53119771 -rwxr-xr-x 3 root root  26292 2010-08-18 10:15 bzip2
Run Code Online (Sandbox Code Playgroud)

您可以看到bunzip2bzcat并且bzip都使用相同的 inode。本质上,它是一个具有三个名称的文件。您可以拥有该文件的三个副本,但为什么呢?它只会不必要地消耗磁盘空间。

  • 该答案根本无法提供在软链接上使用硬链接的任何理由。 (25认同)
  • 但是在 `/bin` 中也有一些符号链接,我想这是混淆的来源之一。为什么有时可执行文件会被符号链接,有时会被硬链接? (14认同)

Arc*_*ege 9

有多种用途。我使用它们来创建基于文件的锁。与大多数其他系统调用不同,link(2) 系统调用是原子的。

另一个用途是在 rsnapshot 中,其中使用硬链接随着时间的推移进行备份以减少磁盘空间量。如果文件未更改,则该文件将硬链接到该文件的旧实例,已更改的文件将重新复制。

我还使用它们来交换服务器上的配置文件:rm file.cfg && ln ~/tmp/file.cfg file.cfg,然后可以安全地删除 ~/tmp/* 文件。

  • 为什么单独的 `ln` 和 `rm` 而不是一个 `mv`? (2认同)

dmc*_*ten 6

添加到已经存在的几个很好的讨论中......

  • 程序的资源访问在 unix 中实现的方式(即“一切都是文件”),意味着操作系统需要用于处理对文件的多个引用的基础结构才能工作,因此这里没有增加成本。
  • 在原始 unix 文件系统中实现目录的方式(即固定格式的(inode, name)对列表意味着文件系统中没有额外的成本来拥有硬链接(好吧,只要我们通过禁止硬链接到目录来防止循环(除了...(这对其他人来说是否开始变得像口齿不清?)))

所以我们免费得到它们。


kkm*_*kkm 6

我可能应该涵盖硬链接的陷阱场景只要原始链接文件存在,硬链接就是具有不同名称和/或不同位置的同一个文件。将文件视为“原始”文件甚至都不正确:两者本身都是目录条目,并且两者(或更多)都是同等的对等体。对于长期存在的文件,这可能是一种祝福,但如果删除其中一个然后创建,即使名称和内容相同,文件也会分开。

假设您创建了一个/foo/myfile链接到/repo/myfile. 两者都是指向相同文件数据的指针;改变一个,另一个改变。但是假设这/repo恰好包含一个 Git 存储库。如果您检出一个不包含myfile在其中的分支,则会/repo/myfile被删除。在这一刻,/foo/myfile变成了 的简单副本/repo/myfile,就像在这对中的另一个断开链接的那一刻一样。当您在分支之间切换文件库发生变化时,很容易甚至不会注意到,但是,当您检出原始分支时,会发现一个文件/repo/myfile由 Git 创建。如果你不注意,你会奇怪为什么这两个文件现在有不同的内容,虽然很容易理解,因为文件之间的硬链接关系不知道它们的名字。相反,软链接将在这个删除-创建循环中存活下来。

另一方面,使用硬链接的软件非常清楚这一点,Git 就是一个很好的例子。Git 几乎免费在同一文件系统上克隆存储库,因为它默认使用硬链接而不是复制文件。对于 Git 来说,硬链接是一个完美的用例,因为它的对象和包文件永远不会改变,所以存储库的一个克隆永远不会修改另一个(Git 知道不要硬链接可修改文件),并且任何克隆都可以在没有任何预防措施的情况下删除:无需跟踪哪个是“原始”并实际包含文件:任何硬链接都是平等的伙伴并“包含”完整文件。软链接在这里不起作用。

硬链接的另一个优点是可以移动任何链接而不会中断对文件内容的访问。对于软链接,移动原始文件会使所有指向它的软链接悬空。

最重要的是,在许多用例中,任一链接类型都同样有效,但在某些类型或其他类型中更有利。此处的许多答案中提到的效率可能与现代机器和文件系统无关,除非您在微不足道的嵌入式控制器的 FLASH 芯片上清理文件系统。在功能上的差异更为重要,通常决定了工程约束和最终的选择:

  • 硬链接“源”可以安全移动,而软链接将断开。
  • 硬链接与其链接的文件无法区分,只要任何硬链接处于活动状态,文件就处于活动状态;软链接是不对称的。
  • 如果删除并重新创建,硬链接节点会脱离链接组,但软链接不会丢失其目标。
  • 软链接可以跨文件系统,硬链接不能。
  • 软链接可能指向一个目录,而硬链接通常不能(实际上总是不应该)。

另外,我必须指出,调用删除文件的库调用是unlink()有原因的!每个目录条目最初只是一个指向其 inode 的单一硬链接。