[Linux]一篇文章带你搞定软硬连接

阅读导览:

  1. 先在windows中先见见软硬连接
  2. 从名字、inode等方面分析软硬连接
  3. 如何实现软硬连接
  4. 硬链接注意事项
  5. 软硬链接都用来干什么
  6. 如何在windows中实现硬链接

在这里插入图片描述

概念

软链接:symbol link(又称符号链接,切记不是soft link)

硬链接:hard link

inode   权限	 链接数 所有者 组 大小 最后修改时间 文件名
----  -----	-----	-	----	------------	-----
929767 -rw-rw-r-- 2 sll sll 0 Apr 14 10:27 hardlink
929768 lrwxrwxrwx 1 sll sll 6 Apr 14 10:28 symbollink -> test.c
929767 -rw-rw-r-- 2 sll sll 0 Apr 14 10:27 test.c

如图所示:

我们创建了一个test.c(当然我没有往里面写内容,因为软硬链接和代码无关)。然后分别创建了一个软链接(symbollink)、硬链接(hardlink),使其链接test.c

我们将从以下几个方面来看待软硬链接

  1. 引入:windows下的快捷方式
  2. 文件名
  3. 文件inode
  4. 链接数

对了,补充一句:软硬连接和动静态库的动静态链接没有关系!

简述文件系统

本文在ext2文件系统的概念下叙述,且仅对本文需要了解的知识进行叙述。

  1. 一个inode唯一标识一个文件。

  2. 文件和目录在文件系统下看来都是一样的(也可理解为都是以数据的方式存储在磁盘中),只不过权限不同。 文件没有d权限,目录有d权限。文件存储的内容是数据(比如c代码),而目录存储的内容也是数据,只不过这个数据是其内部的文件名和其对应的inode映射关系

    例:一般文件

    test.c文件中数据:代码(存储在data block中)
    int add();
    double sub();

    例:目录文件

    dir目录下数据:文件名 — inode(均存储在data block中)
    hardlink — 929767
    symbollink — 929768
    test.c — 929767
  3. 磁盘划分成许多个分区,每个分区的inode独立(即:相同分区的inode不重复,不同分区的inode可能重复),这也就决定了硬链接跨越文件系统进行链接的不可实现性

windows下的快捷方式–软硬链接的直观体现

大家对windows下的快捷方式肯定不陌生,我们常常将一个文件执行添加桌面快捷方式的操作,这个操作实际上就对应了软链接。让我们再深入探究一下其中的奥秘!

先来玩玩找不同

在这里插入图片描述

软链接

上图中,左侧是我的typora.exe文件的存储位置、右侧是其对应的桌面快捷方式(软链接)

对,如果你仔细观察,其实桌面也是一个文件(Desktop),创建桌面快捷方式本质上就是将文件软链接一份到Desktop文件夹中(当然,这都是后话,与今天所要探讨的并无太大关联,如果感兴趣的小伙伴可以去深入了解以下)。再提一嘴,为什么他们的大小和占用空间不同,这和他们的data block的大小相关,这里就不过多叙述了。

可以看到

  1. 他们的文件类型不同
  2. 文件所处的位置自然不同,因为创建的是桌面快捷方式,放到了Desktop文件夹中
  3. 文件的大小不同,这是因为对于左侧的文件,其内容是其本来具有的应用程序的数据,而右侧的文件的内容则可以理解为一个索引(这个内容就是为了让你找到左侧的源文件)

在这里插入图片描述

硬链接

上图中,左侧是我的test.txt文件的存储位置、右侧是其对应的硬链接文件link.txt(这里将他们放入了同一个文件夹中了)

如果你这个时候去删掉他们之间的任意一个后,再去打开另外一个,发现内容还是没有变(就好像删除的操作白做了一样),这是由于硬链接的特性,会在后面进行叙述(不同的是,如果你删除了被软链接链接文件,则你会发现软链接就没有用了,打不开对应的源文件)

可以看到

  1. 他们的文件类型相同(对,他们就是相同的,一模一样,删了一个另一个还在)
  2. 他们的存储大小相同(因为他们都是同一个文件,存储大小自然相同)

小结

综上我们先得出一个简单的小结:对于软链接,这个文件指向了我的源文件(其内容就是我源文件的位置);对于硬链接,这个文件中的内容就是我的源文件内容。

这个时候可能有朋友要提出疑问,那我用硬链接难道是把文件拷贝了一份???不!硬链接并不会拷贝文件,因为开销太大,相反它利用了引用计数的思想,来实现链接,听我娓娓道来。

角度1:文件名

回顾开始的bash界面

inode   权限	 链接数 所有者 组 大小 最后修改时间 文件名
----  -----	-----	-	----	------------	-----
929767 -rw-rw-r-- 2 sll sll 0 Apr 14 10:27 hardlink
929768 lrwxrwxrwx 1 sll sll 6 Apr 14 10:28 symbollink -> test.c
929767 -rw-rw-r-- 2 sll sll 0 Apr 14 10:27 test.c

我们可以明显的发现:他们的文件名不同

硬链接的文件名就是我创建时给他命的名:hardlink

而软链接的文件名我创建的时候命名为symbollink,但是创建出来后却显示是:symbollink -> test.c

这没什么,作用其实就是告诉用户这个是软链接还是硬链接(linux下不采用文件名标识文件,所以名字是啥自然不重要)。对,就这。

角度2:文件inode

如果你仔细观察,就会发现硬链接文件的inode和源文件是一模一样的,但是软链接的inode则不同。

文件名inode
test.c929767
hardlink929767
symbollink -> test.c929768

由于inode是文件的唯一标识,所以就表明了:

  • 硬链接创建的链接文件hardlink,本质上就是给test.c这个文件增加了个名字(实际上也是如此,创建的时候会在当前目录的data block中增加一个hardlink929767的映射关系存入其中)。
  • 软链接创建的链接文件symbollink -> test.c,本质上是创建了一个新的文件,而这个新文件的内容是其源文件的路径(大抵是这样的,可能还会有别的内容,但主要内容就是路径)。

如上就能搞清楚为什么inode会有如此变化。

角度3:链接数

inode   权限	 链接数 所有者 组 大小 最后修改时间 文件名
----  -----	-----	-	----	------------	-----
929767 -rw-rw-r-- 2 sll sll 0 Apr 14 10:27 hardlink
929768 lrwxrwxrwx 1 sll sll 6 Apr 14 10:28 symbollink -> test.c
929767 -rw-rw-r-- 2 sll sll 0 Apr 14 10:27 test.c

链接数,又称为:硬链接数。是用来标记某个文件被硬链接了多少个文件(又可以理解为,这个inode被取了多少个别名)。

如上所示:

由于hardlinktest.c都链接到了node=929767这个文件(即,有两个映射关系),所以该文件的链接数=2

同样,inode=929768这个文件,只有symbollink -> test.c这一个映射关系,所以其硬链接数为1

文件的删除问题

前面我们提到,hardlink硬链接到了test.c这个文件,但是我删除他们中的任意一个,另外一个内容不会产生影响。这是因为其内部采用了引用计数的思想。

当我删除一个文件的时候,如果链接数>1,那么就对该链接数进行–,同时删除该文件名和其inode的映射关系;如果链接数==1,那么就删除映射关系的同时,再将其对应inode标识的文件删除(彻底删除,你就再也找不到了。当然你用数据恢复的手段可能还可以找得到,毕竟删除数据的本质就将inode bitmap对应位置为0,这点本文就不展开讲述,其属于文件系统的知识)

所以我们做一下归纳吧:

  • 硬链接:本质上就是一种给inode取别名的方式,即增加了一份新的映射关系
  • 软链接:本质上就是创建了一个新的文件,和touch指令区别不大(当然,我指的是创建文件的本质)

如何实现软硬连接

软链接

ln -s sorcefile linkname
//例如:
ln -s test.c symbollink

硬链接

ln sorcefile linkname
//例如:
ln test.c hardlink

不要啥玩意都去硬链接

首先,你几乎是所有玩意都可以去软链接(大抵是这样的,只不过需要考虑到”断链“的情况,也就是软链接不会强制检查链接到不存在的文件)

但是,硬链接可不是随随便便就可以去链接的

  1. 绝对不能跨文件系统去进行硬链接

    解释原理:

    由于不同的文件系统中,inode编号允许重复,所以如果跨文件系统实行硬链接,就会导致链接到错误的inode,所以要从根源上禁止

    现象展示:

    在这里插入图片描述

    我们先分别在mylinkfs,test下创建一个文件,结果如下:

    //mylinkfs
    12 -rw-r--r-- 1 root root     0 Apr 14 14:04 test.c
    //test
    793090 -rw-rw-r-- 1 sll sll    0 Apr 14 14:21 test.c
    

    可以发现,对于mylinkfs中的inode编号十分的小,这是因为这个分区刚刚创建初始化文件系统+挂载,所以在里面创建的文件的inode都会从低到高分配。这也表明了他们不属于同一个文件系统。

    进行软链接:

    sudo ln -s path/test.c symbollink
    //生成了如下文件
    lrwxrwxrwx 1 root root    26 Apr 14 14:26 symbollink -> ../../home/sll/test/test.c
    

    很明显可以连接成功

    进行硬链接:

    sudo ln ../../home/sll/test/test.c hardlink
    //有如下告警
    ln: failed to create hard link 'hardlink' => '../../home/sll/test/test.c': Invalid cross-device link
    

    告警:无效的跨设备链接(即非法的跨文件系统链接)

    所以实践证明,我们确实不能跨文件系统进行硬链接

  2. 不能去链接目录(树)

    在此之前我们先解释一个现象:为什么每当创建一个目录的时候,他的链接数都不是1,而是2,甚至我该目录里面做了一些操作后,链接数更大了?

    [sll@SFT:~/test$] mkdir testlinkdir; ls -li
    929771 drwxrwxr-x 2 sll sll 4096 Apr 14 14:36 testlinkdir
    

    可见,链接数是2。原因很简单,让我们进入testlinkdir看看

    [sll@SFT:~/test$] cd testlinkdir/; ll
    drwxrwxr-x 2 sll sll 4096 Apr 14 14:36 ./
    drwxrwxr-x 3 sll sll 4096 Apr 14 14:36 ../
    

    对,就是这个./搞的鬼,它硬链接到的也是testlinkdir目录。

    但是这玩意其实很怪,因为你明明能看到系统中有链接到目录树的玩意,比如./,../,但是你就是不能手动去链接目录(OS不让你硬链接):

    [sll@SFT:~/test$] ln ./testlinkdir/ hardlinkdir
    ln: ./testlinkdir/: hard link not allowed for directory //不让你去链接目录
    

    为什么不让去链接?因为这可能会破坏目录树的结构,导致循环引用问题,例如:

    如果我要从/home去遍历整个目录树,如果这里面我的某个硬链接链接到了/home,那么就会导致这个遍历一直死循环,根本出不来。而对于操作系统,它有把握拍着胸脯说:我保证我的硬链接不会产生循环引用问题,你能保证你的不会吗?我直接给你禁掉,想用?没门!!

软硬链接常见用途

硬链接: 主要用于在文件系统中创建副本,使得多个文件可以共享相同的数据和权限。这在许多客户端/服务器环境中非常有用,因为它允许客户端直接访问服务器上的主文件,而不需要将副本下载到本地。此外,硬链接还可以用于确保文件的安全,即使原文件被删除,只要还有硬链接存在,文件的数据就不会丢失。

软链接: 主要用于创建指向另一个文件或目录的路径。它的应用场景非常广泛,比如当需要在不同的目录中使用相同的文件时,只需要在某个固定目录放上该文件,然后在其他目录下使用软链接链接该文件,这样既节省了磁盘空间,又方便了文件的访问。此外,软链接还可以用于访问那些已经被删除但仍然需要引用的文件,或者用于不在PATH中的二进制文件或其他资源。

如何在windows中实现硬链接

windows+x

打开Windows PowerShell,找到你当前的路径,然后打开资源管理器进入对应的路径,一般是:C:\Users\NAME,然后在该目录下右键创建一个.txt文件(这一步不用Windows PowerShell,用常规方法),然后在Windows PowerShell中输入:

//这里我们创建的源文件叫test.txt,链接文件叫link.txt
fsutil hardlink create C:\Users\NAME\link.txt C:\Users\NAME\test.txt 

打开Windows PowerShell,找到你当前的路径,然后打开资源管理器进入对应的路径,一般是:C:\Users\NAME,然后在该目录下右键创建一个.txt文件(这一步不用Windows PowerShell,用常规方法),然后在Windows PowerShell中输入:

//这里我们创建的源文件叫test.txt,链接文件叫link.txt
fsutil hardlink create C:\Users\NAME\link.txt C:\Users\NAME\test.txt 

然后就创建成功了。

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值