linux 硬链接和软连接(符号连接) 原理

linux 文件存储原理

在linux系统中,文件存储被分为两部分,用户数据和元数据。
用户数据,即文件数据块,是记录文件真实内容的地方。
元数据则是文件的附加属性,如文件大小、创建时间、所有者等信息。
inode号(即索引节点号)是元数据的一部分,是文件的唯一标致。
这里要区分文件名和inode号的区别。文件名是为了方便用户记忆和使用,而系统是通过inode号寻找正确的文件数据块。

在这里插入图片描述
我们可以改通过 stat 查看文件的inode号

[user_00@localhost ~/d1]$ ls
f1  f2  f3
[user_00@localhost ~/d1]$ stat f1
  File: ‘f1’
  Size: 18        	Blocks: 8          IO Block: 4096   regular file
Device: fd02h/64770d	Inode: 805903006   Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/ user_00)   Gid: (  100/   users)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2020-06-11 16:42:05.119863677 +0800
Modify: 2020-06-11 16:41:58.862863004 +0800
Change: 2020-06-12 16:48:12.425140189 +0800
 Birth: -
[user_00@localhost ~/d1]$

可以看到 f1 的 Inode 号是 805903006。
那按照上面的原理,我们重命名文件,或者移动文件的话,inode号和用户数据是不会变的。

[user_00@localhost ~/d1]$ mv f1 ../f1.new
[user_00@localhost ~/d1]$ stat ../f1.new
  File: ‘../f1.new’
  Size: 18        	Blocks: 8          IO Block: 4096   regular file
Device: fd02h/64770d	Inode: 805903006   Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/ user_00)   Gid: (  100/   users)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2020-06-11 16:42:05.119863677 +0800
Modify: 2020-06-11 16:41:58.862863004 +0800
Change: 2020-06-12 16:53:45.688176047 +0800
 Birth: -

我们可以看到 Inode 没有变,也就是说用户数据的地址是没变的。只有文件目录地址和文件名发生了变化。

硬连接和软连接

为了解决文件共享的问题,linux引入了两种连接方式,硬链接(hard link)和软连接(symbolic link 又称符号连接)。一个inode号对应多个文件的时候,这些文件就称为硬连接。或者说硬链接就是一个文件同时有多个文件名。

硬连接

[user_00@localhost ~/d1]$ ln f1 f1.hlink
[user_00@localhost ~/d1]$ ls
f1  f1.hlink  f2  f3  f4
[user_00@localhost ~/d1]$
[user_00@localhost ~/d1]$ stat f1.hlink
  File: ‘f1.hlink’
  Size: 18        	Blocks: 8          IO Block: 4096   regular file
Device: fd02h/64770d	Inode: 805903006   Links: 2
Access: (0644/-rw-r--r--)  Uid: ( 1000/ user_00)   Gid: (  100/   users)
Context: unconfined_u:object_r:user_home_t:s0
Access: 2020-06-11 16:42:05.119863677 +0800
Modify: 2020-06-11 16:41:58.862863004 +0800
Change: 2020-06-12 17:35:38.830013074 +0800
 Birth: -

可以看到 f1.hlink 的 inode 和 f1的 inode 是一样的,仅仅是文件名不一样而已。
由于硬链接是两个文件名对应同一个文件,所以会有一些特性:

  1. 文件有相同的inode和 data block
  2. 只能对已有的文件创建
  3. 删除一个硬链接并不影响其他相同inode号的文件
  4. 硬链接只能针对文件创建,不能针对目录
  5. 不能交叉文件系统创建
[user_00@localhost ~/d1]$ ls -li
total 8
805903006 -rw-r--r--. 2 user_00 users 18 Jun 11 16:41 f1
805903006 -rw-r--r--. 2 user_00 users 18 Jun 11 16:41 f1.hlink
805903007 -rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f2
805878680 -rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f3
805939943 -rw-r--r--. 1 user_00 users  0 Jun 12 17:22 f4

具有相同的inode号


[user_00@localhost ~/d1]$ ln f5 f5.hlink
ln: failed to access ‘f5’: No such file or directory

不能对不存在的文件创建


[user_00@localhost ~]$ ln d1 d1.hlonk
ln: ‘d1’: hard link not allowed for directory

可以看到是不予许为目录创建硬链接的。基于linux的文件存储机制,如果我们给目录创建硬链接,系统是检测不出来的,如果形成目录环那程序会陷入死循环。
比如 有目录 d1/a , d2/b b指向d1,a指向d2,那当我们用 find 查找文件的时候,遍历过程会是 d1/a/b/a/b…陷入无限循环
但是系统里缺有两个目录的硬链接,便是 . 和 …

[user_00@localhost ~/d1]$ ls -ail
total 8
805903005 drwxr-xr-x. 2 user_00 users  62 Jun 12 17:35 .
134217792 drwxr-x---. 8 user_00 users 184 Jun 12 17:13 ..

. 和 … 的 inode 号,就是当前目录和上层目录的 inode 号


至于为什么不能交叉文件系统创建就很容易理解了。inode 在同一个文件系统里是唯一的,如果夸文件系统,则会出现相同的inode号对应不同 data block 的情况。这肯定是不对的。

软连接

软连接和硬连接是完全不同的。
软连接是一个新的文件,文件的用户数据块存放的是原文件的路径名。
like this
在这里插入图片描述
因此软连接没有硬连接那么多限制:

  1. 软连接有自己的文件权限和属性
  2. 可对不存在的文件或目录创建软链接
  3. 软链接可交叉文件系统
  4. 软链接可对文件或目录创建
  5. 创建软链接时,链接计数 i_nlink 不会增加
  6. 删除软链接并不影响被指向的文件,但若被指向的原文件被删除,则相关软连接被称为死链接(即 dangling link,若被指向路径文件被重新创建,死链接可恢复为正常的软链接)
[user_00@localhost ~/d1]$ ln -s f1 f1.slink
[user_00@localhost ~/d1]$ ls -l
total 8
-rwxrwxrwx. 2 user_00 users 18 Jun 11 16:41 f1
-rwxrwxrwx. 2 user_00 users 18 Jun 11 16:41 f1.hlink
lrwxrwxrwx. 1 user_00 users  2 Jun 15 11:17 f1.slink -> f1
-rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f2
-rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f3
-rw-r--r--. 1 user_00 users  0 Jun 12 17:22 f4

可以看到 ls 命令下,软连接是会明确标识出来的。
我们试着修改下软连接的文件权限

[user_00@localhost ~/d1]$ chmod 600 f1.slink
[user_00@localhost ~/d1]$ ls -l
total 8
-rw-------. 2 user_00 users 18 Jun 11 16:41 f1
-rw-------. 2 user_00 users 18 Jun 11 16:41 f1.hlink
lrwxrwxrwx. 1 user_00 users  2 Jun 15 11:17 f1.slink -> f1
-rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f2
-rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f3
-rw-r--r--. 1 user_00 users  0 Jun 12 17:22 f4

f1 以及自身的硬链接 f1.hlink 文件权限都发生了更改,但是身为软连接的 f1.slink 依然坚挺,并未改变。


那如果我给一个不存在的文件创建软连接呢?

[user_00@localhost ~/d1]$ ln -s f5 f5.slink
[user_00@localhost ~/d1]$ ls -l
total 8
-rw-------. 2 user_00 users 18 Jun 11 16:41 f1
-rw-------. 2 user_00 users 18 Jun 11 16:41 f1.hlink
lrwxrwxrwx. 1 user_00 users  2 Jun 15 11:17 f1.slink -> f1
-rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f2
-rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f3
-rw-r--r--. 1 user_00 users  0 Jun 12 17:22 f4
lrwxrwxrwx. 1 user_00 users  2 Jun 15 11:27 f5.slink -> f5
[user_00@localhost ~/d1]$
[user_00@localhost ~/d1]$ cd f5.slink
-bash: cd: f5.slink: No such file or directory
[user_00@localhost ~/d1]$
[user_00@localhost ~/d1]$ cat f5.slink
cat: f5.slink: No such file or directory
[user_00@localhost ~/d1]$

事实上,可以给一个不存在的目录或者文件创建软连,但是创建的软连是死链接。但是如果软连接的指向被重新创建,那它就复活了,恢复为正常的软连接。神奇吧。

[user_00@localhost ~/d1]$ ls -l
total 12
-rw-------. 2 user_00 users 18 Jun 11 16:41 f1
-rw-------. 2 user_00 users 18 Jun 11 16:41 f1.hlink
lrwxrwxrwx. 1 user_00 users  2 Jun 15 11:17 f1.slink -> f1
-rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f2
-rw-r--r--. 1 user_00 users  0 Jun 11 16:30 f3
-rw-r--r--. 1 user_00 users  0 Jun 12 17:22 f4
-rw-r--r--. 1 user_00 users 11 Jun 15 11:30 f5
lrwxrwxrwx. 1 user_00 users  2 Jun 15 11:27 f5.slink -> f5
[user_00@localhost ~/d1]$
[user_00@localhost ~/d1]$ cat f5.slink
I am live;

我们重新创建了 f5 ,通过软连接也可以顺利找到 f5。


还有一个问题是,软连接是否会导致 links 数增加呢。
有兴趣的朋友自己思考下吧。

### 硬链接链接的区别 在Linux文件系统中,硬链接链接提供了不同的方式来关联文件。两者的主要区别在于工作原理以及适用范围。 #### 硬链接特性 硬链接指向的是inode节点而非路径名。这意味着即使原始文件被重命名或移动到其他目录下,通过硬链接仍然可以访问该文件的内容[^1]。创建一个新的硬链接不会增加磁盘空间占用量,因为多个名称共享同一份实际数据副本。然而需要注意的是,无法为目录建立硬链接,并且所有指向相同inode的链接都具有平等地位——删除任何一个都不会影响其余部分。 ```bash ln source_file hard_link_name ``` 此命令用于生成指定源文件的一个新硬链接名为`hard_link_name`. 要移除一个已存在的硬链接,则只需像处理普通文件那样操作即可: ```bash rm hard_link_name ``` 这只会减少相应inode上的链接计数而不会真正清除物理存储中的资料除非其计数值降到了零表示没有任何有效入口指向它时才会彻底释放资源. #### 链接特点 相比之下,符号链接(即所谓的“链”)保存着目标对象的位置信息(绝对路径或相对路径)。如果原文件位置发生变化则可能造成悬空状态;另外当尝试读取不存在的目标时会返回错误提示。不过好处是可以跨分区甚至网络挂载点之间建立联系而且能够针对整个目录树结构进行映射。 创建链接的方法如下所示: ```bash ln -s target_path symbolic_link_name ``` 这里`target_path`是要链接的对象的具体地址,而`symblic_link_name`则是赋予的新快捷方式的名字. 对于不再需要使用的链接同样可以通过简单的unlink指令予以消除: ```bash unlink symbolic_link_name ``` 这种方式仅废止特定的指针关系而不触及背后的数据实体本身.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

csw_coder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值