豁然高

导航

理解 Linux 的硬链接与软链接

连接命令

 

 ln [选项] 源文件 目标文件

 

选项:
-s:建立软链接文件。如果不加 "-s" 选项,则建立硬链接文件;
-f:强制。如果目标文件已经存在,则删除目标文件后再建立链接文件;

 

分区的组成:元数据区和块区

如果要想说清楚 ln 命令,则必须先解释下 ext 文件系统(Linux 文件系统)是如何工作的。

linux系统分区的格式化就是写入文件系统,而我们的 Linux 目前使用的是 ext4 文件系统。如果用一张示意图来描述 ext4 文件系统,则可以参考图 1。

 

 

 

ext4 文件系统会分区主要分为两大部分(暂时不提超级块):小部分用于保存文件的元数据的元数据区;剩余的大部分用于保存实际块数据(block)的块区。

元数据的默认大小为 128 Byte,保存的是文件本身的信息,如文件的inode号权限(r、w、x)、文件的所有者属组文件的大小文件的状态改变时间(ctime)文件的最近一次读取时间(atime)文件的最近一次修改时间(mtime)、文件的数据真正保存的 block 编号。注意,元数据中不包括文件名,文件名是保存在目录文件的block中的。

块数据(block) 的大小可以是 1KB、2KB、4KB,默认为 4KB。block 用于存储文件的实际要存储的数据。如果一个 block 放不下数据,则可以占用多个 block。例如,有一个 10KB 的文件需要存储,则会占用 3 个 block,虽然最后一个 block 不能占满,但也不能再放入其他文件的数据。这 3 个 block 有可能是连续的,也有可能是分散的。

文件的组成:元数据和块数据

也就是说,linux系统中,一个文件由保存文件本身信息的元数据和保存实际数据的块数据(block)两个部分组成。元数据中有blcok编号,通过这个block编号才能找到实际的数据块。

 

目录文件和普通文件的block

目录也是文件,其元数据的内容和普通文件大体相同,主要保存文件的inode号,权限(r、w、x)、文件的所有者和属组、文件的大小、文件的状态改变时间(ctime)、文件的最近一次读取时间(atime)、文件的最近一次修改时间(mtime)、文件的数据真正保存的 block 编号。

目录的块数据(实际数据)保存的是一级子目录名或者文件名和inode号的对应关系。前面说过,文件名并不保存在文件的元数据中,而是保存在管理这个文件的目录文件的块数据中。我们通过文件名寻找文件,首先要找到保存这个文件的目录文件的block中保存的与文件名对应的inode号,通过inode号才能找到文件的元数据,再通过元数据中的block编号,找到文件的快数据(实际数据)。

普通文件的块数据中并不保存文件名和inode号的对应关系,而是保存文字列,图片数据等我们真正需要保存的数据。

 

硬链接

元数据中的inode号是文件的唯一标识, 可以通过ll -i 来查看文件的inode号。注意,同一个文件只有唯一的inode号,但可以有不同的文件名,这就是所说的硬链接。

前面说目录文件中的块数据中保存的是目录子文件的文件名和inode号的对应关系,那我们可以在同一个目录或者不同的目录文件的块数据中保存多个不同的文件名对应同一个inode号,这样不论你访问的是哪一个文件名,其实访问的都是同一个数据块。

实现这种多个文件名对应同一个inode号的方式就是硬链接

ln  源文件 目标文件

[root@localhost tmp]# mkdir test-folder  //创建目录
[root@localhost tmp]# cd test-folder  //进入创建的目录
[root@localhost test-folder]# touch test-file  //创建文件
[root@localhost test-folder]# ll -i test-file  //查看创建文件的inode号,为3937
3937 -rw-r--r-- 1 root root 0 Oct 18 06:56 test-file
[root@localhost test-folder]# ln test-file test-file-hard1  //在同一个目录下创建硬链接
[root@localhost test-folder]# ll -i   //查看目录下的文件的inode号,可以发现两个不同的文件名有相同的inode号
total 0
3937 -rw-r--r-- 2 root root 0 Oct 18 06:56 test-file
3937 -rw-r--r-- 2 root root 0 Oct 18 06:56 test-file-hard1
[root@localhost test-folder]# mkdir /tmp/test-folder2   //创建另一个目录
[root@localhost test-folder]# ln test-file /tmp/test-folder2/test-file-hard2  //创建硬链接到另一个目录
[root@localhost test-folder]# ll -i /tmp/test-folder2/test-file-hard2  //查看硬链接文件的inode号,可以发现其与之前的文件的inode号相同
3937 -rw-r--r-- 3 root root 0 Oct 18 06:56 /tmp/test-folder2/test-file-hard2

初始创建的文件test-file,会在分区中创建元数据并分配块(块的编号为元数据中的block编号),然后在目录文件的块数据中增加新建文件名和元数据中inode的对应关系。

硬链接创建的文件其实并没有增加新的文件(即没有在分区中增加新的元数据和块数据),只是在相应的目录文件的块数据中增加了一个文件名和源文件的inode号的对应关系

 

硬链接的示意图如下

 

 

当我们查找一个文件,比如 /root/test 时,要经过以下步骤:

  1. 首先找到根目录的 inode(根目录的 inode 是系统已知的,inode 号是 2),然后判断用户是否有权限访问根目录的 block。
  2. 如果有权限,则可以在根目录的 block 中访问到 /root 的文件名及对应的 inode 号。
  3. 通过 /root/ 目录的 inode 号,可以查找到 /root/ 目录的 inode 信息,接着判断用户是否有权限访问 /root/ 目录的 block。
  4. 如果有权限,则可以从 /root/ 目录的 block 中读取到 test 文件的文件名及对应的 inode 号。
  5. 通过 test 文件的 inode 号,就可以找到 test 文件的 inode 信息,接着判断用户是否有权限访问 test 文件的 block。
  6. 如果有权限,则可以读取 block 中的数据,这样就完成了 /root/test 文件的读取与访问。


按照这个步骤,在给源文件 /root/test 建立了硬链接文件 /tmp/test-hard 之后,在 /root/ 目录和 /tmp/ 目录的 block 中就会建立 test 和 test-hard 的信息,这个信息主要就是文件名和对应的 inode 号。但是我们会发现 test 和 test-hard 的 inode 信息居然是一样的,那么,我们无论访问哪个文件,最终都会访问 inode 号是 262147 的文件信息。

这就是硬链接的原理。硬链接的特点如下:

  • 不论是修改源文件(test 文件),还是修改硬链接文件(test-hard 文件),另一个文件中的数据都会发生改变。
  • 不论是删除源文件,还是删除硬链接文件,只要还有一个文件存在,这个文件(inode 号是 262147 的文件)都可以被访问。
  • 硬链接不会建立新的 inode 信息,也不会更改 inode 的总数。
  • 硬链接不能跨文件系统(分区)建立,因为在不同的文件系统中,inode 号是重新计算的。
  • 硬链接不能链接目录,因为如果给目录建立硬链接,那么不仅目录本身需要重新建立,目录下所有的子文件,包括子目录中的所有子文件都需要建立硬链接,这对当前的 Linux 来讲过于复杂。


硬链接的限制比较多,既不能跨文件系统,也不能链接目录,而且源文件和硬链接文件之间除 inode 号是一样的之外,没有其他明显的特征。这些特征都使得硬链接并不常用,大家有所了解就好。

 

软连接

软连接也是通过ln命令来实现,只是需要 -s 选项

ln -s 源文件 目标文件

硬链接的建立不会在分区中创建新的元数据和数据块,但是软连接的创建会创建新的元数据和数据块,只是软连接文件的数据块中保存的不是普通文件那样的数据,而是保存源文件的路径(相对或者绝对)及inode号

软连接文件是通过其数据块中保存的源文件的路径来寻找源文件的。(路径的相对或者绝对,取决于创建链接时使用的是相对还是绝对路径)

 

软连接文件的块数据和目录文件的块数据有些类似,只是软连接文件的块数据中只保存源文件的文件名和inode号的对应关系,而目录中可以保存多个对应关系

 

软连接的示意图如下

 

 

 

硬链接和软连接的区别

硬链接不创建新的元数据和数据块,只是在相应的目录文件的块数据中增加了一个硬链接的文件名和源文件inode号的对应关系。

软连接会创建新的元数据和数据块,在相应目录文件中保存的是软连接文件名和软连接文件的inode号,而不是源文件的inode号,源文件的inode号保存在新建的软连接文件的块数据中。

硬链接文件和源文件具有相同的inode号,软连接文件具有独立的元数据和数据块,所以软连接文件具有和源文件不同的inode号

 

 

由于硬链接是有着相同 inode 号仅文件名不同的文件,因此硬链接存在以下几点特性:

  • 文件有相同的 inode 及 data block;
  • 只能对已存在的文件进行创建;
  • 不能交叉文件系统进行硬链接的创建;
  • 不能对目录进行创建,只可对文件创建;
  • 删除一个硬链接文件并不影响其他有相同 inode 号的文件。

软链接有着自己的 inode 号以及用户数据块。因此软链接的创建与使用没有类似硬链接的诸多限制:

  • 软链接有自己的文件属性及权限等;
  • 可对不存在的文件或目录创建软链接;
  • 软链接可交叉文件系统;
  • 软链接可对文件或目录创建;
  • 创建软链接时,链接计数 i_nlink 不会增加;
  • 删除软链接并不影响被指向的文件,但若被指向的原文件被删除,则相关软连接被称为死链接(即 dangling link,若被指向路径文件被重新创建,死链接可恢复为正常的软链接)。

 

硬链接文件和源文件不管哪一个移动后都可以正常使用,因为inode不变,移动后仍然可以找到用户数据块

软连接的文件的源文件如果位置变动了,则软连接文件无法再使用,因为软连接文件中的用户数据块中保存的源文件路径名已经找不到原文件

如果软连接文件使用的是绝对路径,则软连接文件移动后仍可使用。如果使用的是相对路径,则软连接文件移动后无法再用,因为移动后找不到原文件

 

posted on 2019-10-18 15:39  豁然高  阅读(243)  评论(0编辑  收藏  举报