Linux 之 符号链接与硬链接

链接简单理解就是,添加一个对文件/文件夹的访问副本,更方便平时的一些操作。类比Windows的快捷方式。

简单先看一下符号链接与硬链接的生成与使用。

生成符号链接与硬链接

  • 创建符号链接:ln -s target_file link_file

  • 创建硬链接:ln target_file link_file

演示:

创建文件的符号链接

$ ln -s file1 file_symlink

创建文件的硬链接

$ ln file1 file_hardlink

创建文件夹的符号链接

$ ln -s link_test_dir dir_symlink

创建文件夹的硬链接:创建失败

$ ln -s link_test_dir dir_hardlink
ln: link_test_dir: hard link not allowed for directory

从上面的流程和截图的观察中,可以总结几点:

  • 在表现形式上(ls -alh查看):
    • 符号链接表现为指向被链接文件的形式,硬链接表现为单独的文件。
    • 符号链接权限为lrwxrwxrwx.,硬链接权限与源文件一致
    • 硬链接大小与源文件一致,符号链接大小为被链接文件的路径字符长度
  • 硬链接不允许创建给目录,符号链接可以。
  • 访问文件:都是源文件的值

做一些操作,再观察现象:

  • 修改权限

    • 修改硬链接权限

    • 修改软连接权限

  • 修改属主

    • 修改硬链接属主

    • 修改软连接权限

  • 删除源文件后,再访问符号链接和硬链接

总结以上情况,我们可以再补充一些符号链接跟硬链接的特点:

  • 访问符号链接和硬链接实际都是访问被链接文件;
  • 硬链接修改权限/属主时,源文件跟着一起变;符号链接修改权限/属主时,链接文件未变化,实际变化的是源文件,且硬链接文件的属性跟着一起变动;
  • 源文件被删除时,硬链接文件仍然可以访问,且与源文件一致;访问符号链接文件时会找不到对象。

按上面的操作,基本可以运用符号链接和软连接。但是留有一些疑问:

  • 为什么源文件删除了,硬链接还能正常访问,而符号链接却失效了?
  • 为什么修改符号链接的属主/权限,符号链接的属主/权限却未变动,变动的是源文件?
  • 为什么硬链接的所有文件属性都跟源文件保持一致?
  • 为什么硬链接不能链接给目录?

要解答这些问题,可以先延伸看下Linux文件系统的管理模式。

Linux文件管理

当我们使用Linux文件系统时,文件系统通常会将文件的两部分数据分别放在不同的区块中:权限与属性放置在inode中,实际数据放置在data block中。另外,还有一个超级区块 (superblock) 会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等。

每个 inode 与 block 都有编号,这三个数据:

  • superblock:记录所在 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式与相关信息等;
  • inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block号码;
  • block:实际记录文件的内容,若文件太大时,会占用多个 block 。

这种数据存取的方法我们称为索引式文件系统(indexed allocation)

当我们在 Linux 下的文件系统创建一个目录时,文件系统会分配一个 inode 与至少一块 block给该目录。其中,inode 记录该目录的相关权限与属性,并可记录分配到的那块 block 号码;而 block 则是记录在这个目录下的文件名与该文件名占用的 inode 号码数据

文件寻址过程

整个文件系统的目录结构就如一个树状图,从根目录开始,从目录的inode获取它的block。从block中获取子目录的inode值,持续往下寻址直到找到对应文件。

以上一节的源文件/home/jingx/test_link_dir/file1为例,文件系统访问这个文件的流程如下:

  1. 找到"/"挂载点,获取root inode。

PS:在往下搜寻的时候,如果有新的挂载点,会重新获取root inode。当前仅讨论简单情况。

  1. 通过root inode找到对应block,继续往下寻找下一个目录的inode。通过inode获取文件权限属性,check当前用户的操作是否有权限继续;如果有权限,则通过inode指向的block搜寻下一层,直到搜索到最终文件:home/jingx/test_link_dir/file1。

  2. 最终找到对应文件的inode,从inode中获取文件属性和block号;从block号获取文件内容。这就是一次完整的文件寻址过程。

硬链接实现

从上一节知道了文件的寻址过程。现在来看硬链接的具体实现方式:

  • 硬链接某一个文件时,实际上是在对应父目录的block中,添加一条 inode:硬链接文件名 的记录。通过ls -il命令可以输出对应文件的inode号。可以看到源文件和硬链接文件,其实是同一个inode号

如果硬链接文件在其他目录,也是同样在对应目录的block中添加一条指向文件实际inode的记录。

同时观察输出的第三列属性,因为当前有3个对象指向这个inode,所以这个inode的引用为3。

PS:直到inode引用为0时,这个文件才从文件系统认定被删除。

所以建立文件的硬链接,实际上就是在对应目录的block中新建一条记录,并非新增一个文件

符号链接

对比硬链接的实现,符号链接实际上是一个真实存在的文件。

  • 它是一个跟普通文件一样,存在于硬盘中,有自己的inode编号和block。

  • inode中标明它的文件类型是符号链接(权限中的第一位l);

  • 显示权限为777,但实际权限是跟父目录及被链接对象有关:

    • 如果是对符号链接本身的操作(删除或修改指向),则根据操作用户在父目录的权限来执行;

    • 如果是对符号链接指向对象的操作(chmod、chown、cp等),则根据操作用户在被链接对象的权限来执行;

  • 符号链接文件实体内容则只有被链接文件的路径。存储位置根据链接格式(local、extend)有关,在此不赘述;

遗留问题回答

根据上面描述的硬链接和符号链接的特点,可以回溯文章开始提出的一些问题:

  • 为什么源文件删除了,硬链接还能正常访问,而符号链接却失效了?

    因为删除源文件的操作,实际上是在它父目录的block中删掉类似对应的 文件名:inode 的指向。实际的文件内容(inode、block)并没有删掉。硬链接还可以根据本身的inode号进行文件寻址。而符号链接实际保存的是源文件的路径,所以访问符号链接时候,会根据路径去寻找文件。而源文件删除后,该路径的文件记录已经不存在了,所以会导致No such file or directory

  • 为什么修改符号链接的属主/权限,符号链接的属主/权限却未变动,变动的是源文件?

    因为像chmod/chown等命令做操作的时候,会递归的去对最终文件进行操作。所以修改属主/权限的操作实际是针对源文件的。

    因为这个原因,导致了符号链接的提权类问题。由于操作、符号链接所在目录、源文件三者的权限不一致,可能导致通过伪造符号链接等方式进行提权操作。如果添加"-h"参数,则会在操作的时候忽略符号链接文件。以此来防止

  • 为什么硬链接的所有文件属性都跟源文件保持一致?

    因为硬链接文件的inode和源文件的inode是同一个,而inode是存储文件属性的位置。

  • 为什么硬链接不能链接给目录?

    为了防止路径回环。回忆之前说的文件寻址模式,是通过树状来进行寻址。假设将/a/b/hardlink_dir链接到/a上,由于a和hardlink_dir都是同一个inode,在寻址逻辑上会变成hardlink_dir既是b的子目录又是b的父目录(a)。在内核的处理上复杂度变变的更高,所以从使用工具层面上禁止了目录的硬链接。

    PS:在系统中实际是存在两个特殊的硬链接,即:....指向目录本身,..指向父目录。因为系统对它们做了特殊处理,所以不会有路径回环的问题发生。

  • 补充:硬链接也不能跨文件系统进行链接,因为寻址模式、inode存储方式以及superblock在不同的文件系统间是不一样的。而软链接可以跨文件系统链接,因为软链接只存储被链接文件的路径,根据路径进行寻址这个是文件系统的共性。

Reference

linux创建的硬链接为什么不占用磁盘空间?

Linux系统如何知道某文件在硬盘中的位置?

XFS的on-disk组织结构(13)——Inode datafork of symlink file

linux为什么不能硬链接目录?

posted @ 2022-03-12 19:10  Jing-X  阅读(1052)  评论(0编辑  收藏  举报