Linux中的文件、硬链接和软连接
我一直对自己对 Linux 中的 inode、硬链接和软链接的肤浅理解感到困扰。在这里,我尝试将我的学习结构化为一个简化的思维模型。欢迎指正。
Linux中的文件、硬链接和软连接
Linux中文件是什么?
在存储层面,文件是数据块。在文件系统级别,此数据块表示为称为inode的抽象。将 inode 视为存储有关底层数据块的元数据的数据结构。路径名 使得这一对(inode,数据块)可供人类访问和使用。
以这种方式思考整体 - 文件的数据块位于比路径名(位于文件系统级别)更低的抽象级别。inode 充当桥梁 - 文件系统级别的数据块的代表。
文件的组成部分。从下往上依次为数据块、inode 和路径名
大致来说,文件 = 路径名 + inode + 数据块。
因此,当您谈论文件时,您可能指的是其中部分或全部组件。
硬链接
现在,如果我们将路径名视为贴在(inode,数据块)对上的标签,那么我们可以用不同的标签引用同一个 inode。
两个路径名/tmp/filename1
指向/home/bhoot/filename2
同一个 inode,因此代表两个硬链接。
上图可以有多种解读:
- 路径名指向 inode,而不是相反。因此,路径名知道 inode,但 inode 不知道路径名。
- 在这个抽象层次上,我们能分辨出这两个路径名中的哪一个最初创建了该文件吗?我认为不能。硬链接的地位应该是平等的。
- 作为上述观点的必然结果,两个文件至少有一个硬链接。当文件被创建之时时,touch一个文件就是创建了一个文件路径和对node的硬链接
删除硬链接
参考上图。如果你这样做rm /tmp/filename1
,从理智的角度来看应该会发生什么?
该命令是否应删除整个*/tmp/filename1 + inode + 数据块*/home/bhoot/filename2
组合?那么指向同一 inode 的 其他路径名会发生什么?
正确的方法是保留其他路径名的完整性/home/bhoot/filename2
,同时仅删除目标路径名/tmp/filename1
。
这就是当您删除文件时发生的情况 -指定路径名和 inode 之间的(硬)链接被删除。
类似地,mv f1 f2
创建一个新的硬链接f2
并删除旧的硬链接f1
。
表示要删除链接到同一 inode 的两个硬链接之一。仅删除受影响的路径名。inode 和底层数据块保持不变。
如果删除了指向某个文件的所有硬链接,会发生什么情况?现在,文件系统中不再有指向该数据块的路径名。因此,该 inode 被标记为删除,并且关联的数据块变为孤立块。
当指向 inode 的所有硬链接被删除时,整个文件连同其内容都会从文件系统中删除。
软链接
参考下图
/home/bhoot/filename2常规文件由左侧的 路径名标识。软链接文件由filename3右侧的路径名标识。链接文件指向常规文件。常规文件和链接文件都有自己的 inode 和自己的数据块
上图显示了一个蓝色的软链接(是蓝色的,对吧?)从链接文件指向filename3
目标文件/home/bhoot/filename2
。软链接****或符号链接将软链接文件指向目标文件。
因此,软链接将链接文件链接到目标文件。这与将路径名链接到 inode 的硬链接相反。
软链接是一个文件
正如我们在 Linux 中的文件是什么?部分中看到的,路径名始终链接到inode + 数据块。软链接也是如此。在上图中,filename3
指向的软链接文件/home/bhoot/filename2
也有自己的 inode 和数据块。
您可以使用命令检查与路径名关联的 inode 编号ls -i
。指向相同 inode 的两个硬链接文件将打印相同的 inode 编号,而软链接文件及其目标文件将打印不同的 inode 编号。
1 | create a regular file |
软链接文件的内容
软链接关系是如何存储的?在软链接文件的数据块中。软链接的内容是它指向的目标文件的路径名。
有两种方法可以验证这一点:
readlink filename3
打印软链接的内容filename3
,即目标路径名的名称。1
2readlink filename3
/home/bhoo/文件名2stat --format="%s" filename3
打印的大小filename3
,该大小等于名称中的字符数/home/bhoot/filename2
。1
2stat --format="%s" filename3
21
软链接的I/O操作
复制软链接文件
复制软链接文件时会发生什么?一定条件下,与复制常规文件时的情况相同。或者我是这么认为的。
1 | create a regular file |
发生了什么?该cp
命令只是复制了目标文件,而不是链接文件。
默认情况下,cp
的工作方式如上所述,但cp -P
会复制软链接本身,即软链接的 inode 和数据块。
移动软链接文件
移动软链接文件时会发生什么?这更容易预测。幸运的是,与移动常规文件时发生的情况相同 - 创建新的路径名条目,同时删除旧的路径名条目。由于新路径名仍然指向相同的旧 inode + 数据块,因此它也指向相同的目标文件。
移动软链接文件会将旧软链接的路径名替换为新路径名。新路径名仍然指向相同的目标文件。
移动目标文件
一个更有趣的问题值得我们思考:当目标文件被移动或者删除时,会发生什么情况呢?我们来看一个严重删除的案例。
移动或删除目标文件是更具破坏性的操作
A soft link file depends on its content to determine which file it points to. Even when the target file is deleted, the content of soft link file doesn’t change, i.e., it still keeps pointing to the now deleted target file. With its purpose existing no more, the soft link thus becomes a dangling, dead link.
结束语
在我看来,硬链接和软链接这两个术语有点令人困惑,因为它们听起来像是用于类似目的的不同工具。但是,硬链接作为将路径名链接到 inode 的目录条目而存在,而软链接作为将其自身路径名链接到另一个路径名的文件而存在。
所以,从结构存在的角度来说,硬链接其实看起来比软链接更软。
参考
*
man 7 inode
man 7 symlink
man 7 path_resolution
- Pádraig Brady 的 《符号链接、硬链接和重新链接的再解释》也从这个角度补充了reflinks。在文件系统级别上,数据块似乎只由一个 inode 表示。但 reflinks 实现了 inode 和数据块之间的多对一映射。
1 | 摘要:符号链接引用名称,硬链接引用元数据,而重新链接引用数据。 |