硬链接和软链接

在 Linux 中有两种 link(链接)的概念,一般称之为硬链接和软链接(或符号链接)。在理解链接之前最好了解一下 inode 索引节点

硬链接

一般情况下,文件名和 inode 号码是"一一对应"的关系,每个 inode 号码对应一个文件名(每个文件默认有一个硬链接)。但是,Unix/Linux 系统允许多个文件名指向同一个 inode 号码。

这意味着,可以用不同的文件名访问同样的内容,对文件内容进行修改后,会影响所有文件名。但是,删除一个文件名,不影响另一个文件名的访问。这种情况就被称为"硬链接"(hard link)。

创建一个硬链接,就会为文件创建了一个新的文件名。硬链接有两个重要局限性:

  1. 硬链接不能链接不在同一系统的文件。也就是说硬链接不能链接与文件不在同一磁盘分区上的文件;
  2. 硬链接不能链接目录。

一个硬链接和文件本身没有什么区别。当你列出一个包含硬链接的文件时,不会有特殊的链接指示说明。当一个硬链接被删除时,文件本身的内容仍然存在(也就是说,它所占的磁盘空间不会被重新分配),直到所有关联这个文件的硬链接都删掉。

使用 ln 命令创建硬链接:
[Linux]$ ln abc.txt def.txt
[Linux]$ ls -li
total 24
152410 drwxrwxr-x 2 shiyanlou shiyanlou 4096 Aug 17  2016 Desktop
152067 -rw-rw-r-- 2 shiyanlou shiyanlou 7805 Jan 16 15:14 abc.txt
152067 -rw-rw-r-- 2 shiyanlou shiyanlou 7805 Jan 16 15:14 def.txt

运行上面的命令后,多出一个 def.txt 文件,而且两个文件的 inode 号相同。inode 信息中的“链接数”会增加 1。

反过来,删除一个文件名,就会使得 inode 节点中的"链接数"减 1。当这个值减到 0,表明没有文件名指向这个 inode,系统就会回收这个 inode 号码,以及其所对应 block 区域。

注解

目录文件的硬链接

创建目录时,默认会生成两个目录项: .... 相当于当前目录的硬链接; .. 相当于父目录的硬链接。所以,目录的硬链接总数,等于 2 加上它的子目录总数(含隐藏目录)。其实使用 ln -d 命令也允许 root 用户尝试建立目录硬链接。

这些都说明系统限制对目录进行硬链接只是一个硬性规定,并不是逻辑上不允许或技术上不可行。为什么操作系统要进行这个限制呢?

由于 Linux 操作系统中的目录是以 / 为节点的树状结构,对目录的硬链接有可能破坏这种结构,甚至形成循环如: /usr/bin -> /usr/ ,在使用遍历目录的命令时(如: ls -R )系统就会陷入无限循环中。软链接的 inode 号码不一样,所以不会出现这种问题。

软链接(或符号连接)

除了硬链接以外,还有一种软链接,创建软链接是为了克服硬链接的局限性。

软链接是通过创建一个特殊类型的文件(指针)链接到文件或目录。就像是 Windows 的快捷方式,当然,符号链接早于 Windows 的快捷方式很多年。

文件 A 和文件 B 的 inode 号码虽然不一样,但是文件 A 的内容是文件 B 的路径。读取文件 A 时,系统会自动将访问指向文件 B。因此,无论打开哪一个文件,最终读取的都是文件 B。但是,文件 A 依赖于文件 B 而存在,如果删除了文件 B,打开文件 A 就会报错:"No such file or directory"。这是软链接与硬链接最大的不同:文件 A 指向文件 B的文件名,而不是文件 B 的 inode 号码。

提示

软链接的应用

想象这样一个情景,一个程序需要使用 foo_1.1 文件中的共享资源,由于 foo 经常改变版本号。每次升级后都得将使用 foo_1.1 的所有程序更新到 foo_1.2 文件,那么每次更新 foo 版本后,都要重复上边的工作。

符号链接能很好的解决这个问题。比如,创建一个 foo 的软链接指向 foo_1.2。这时,当一个程序访问 foo 时,实际上是访问 foo_1.2。当升级到 foo_1.3 时,只需要更新软链接指向。这不仅解决了版本升级问题,而且还允许在系统中保存两个不同的版本,如果 foo_1.3 有错误,再更新回原来的 foo_1.2 链接就可以。

使用 ln -s 命令创建软链接:

[Linux]$ ln -s abc.txt aaa
[Linux]$ ls -l
total 8
lrwxrwxrwx 1 shiyanlou shiyanlou    7 Jan 16 17:49 aaa -> abc.txt
-rw-rw-r-- 1 shiyanlou shiyanlou 7805 Jan 16 17:49 abc.txt