Linux - 通过软硬链接学习inode

​ 说到软硬链接,首先要了解inode是什么,了解了inode的结构,会有助于区分软硬链接


inode

inode 内容

Linux系统中,每个文件都有对应的inode,而inode作为数据索引的标识符,其中包含了一个文件的基本信息,如inode编号,修改时间,文件的位置等。所以linux中不使用文件名,而是使用inode号来识别文件。

通常打开一个文件的步骤也就被系统大致的拆分为三个步骤:

  1. 找到目标文件对应的inode
  2. 通过inode号,获取出inode信息
  3. 根据获取出的信息,找到文件数据所在的block,读取内容

为了更直观得看到inode的信息,先新建一个文件,使用stat命令查看inode相关信息

[root@suhw ~]# touch file.txt 
[root@suhw ~]# stat file.txt 
  File: ‘file.txt’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 33575038    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2020-09-27 09:53:29.477000000 +0800
Modify: 2020-09-27 09:53:29.477000000 +0800
Change: 2020-09-27 09:53:29.477000000 +0800
 Birth: -

其中较为关键的几个字段说明如下

字段解释
File文件名
size文件大小
Blocks文件所占用的块数
Device文件所在设备号,分别以十六进制和十进制显示
Inode文件节点号
Links对应的链接数,有多少个文件名指向该inode(硬链接会增加该值)

inode 使用情况

inode也会消耗硬盘空间,所以格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区,存放inode所包含的信息。每个inode的大小,一般是128字节或256字节。通常情况下不需要关注单个inode的大小,而是需要重点关注inode总数。inode总数在格式化的时候就确定了。

可以通过df -i查看inode使用情况

[root@suhw ~]# df -i
Filesystem               Inodes IUsed   IFree IUse% Mounted on
/dev/mapper/centos-root 8910848 26547 8884301    1% /
devtmpfs                 998093   369  997724    1% /dev
tmpfs                   1001108     1 1001107    1% /dev/shm
tmpfs                   1001108   455 1000653    1% /run
tmpfs                   1001108    16 1001092    1% /sys/fs/cgroup
/dev/sda1                524288   327  523961    1% /boot
tmpfs                   1001108     1 1001107    1% /run/user/0

inode 结构

我们可以简单的将linux中的文件看做是 **inode+数据块 **组成。

首先需要了硬盘的最小存储单位叫扇区(Sector),每个扇区能存储大小为512字节(0.5KB),操作系统在读取硬盘时,不会一个一个扇区读,而是一次读取一个块(block), 所以块是文件存取的最小单位。一般常见块的大小为4KB,也就是八个扇区组成的。(以下都默认块大小为4KB)

块大小可以通过如下方式查看,其中IO Block就说明了当前块大小为4KB。

[root@suhw ~]# stat /boot/|grep "IO Block"
  Size: 4096      	Blocks: 8          IO Block: 4096   directory

但是inode是如何访问到数据块的呢,通过下面计算 最大文件大小 的例子来帮助理解


最大文件大小

接下来讨论ext3文件系统下单个文件所能占用最大空间,有些前提条件需要明确:

  1. ext3文件系统采用32bit的块地址索引空间;
  2. inode条目中,引用一个块空间符号需要4byte的大小;
  3. 对于一个inode来说,设计了12个直接指针索引,一个间接指针索引,一个双间接指针索引,以及一个三间接指针索引。

下图就是inode的大体结构示意图。可以从图中看出,inode中除了描述了一些文件相关信息外,最主要的就是维护了与数据库之间的索引关系。

image-20200928105026758

我们目前所用的文件系统可归类为“索引式文件系统”,最简单粗暴的设计就是为一个文件所需要的所有block建立一个索引表,其中第n个元素就存着第n个块所对应的地址,这样访问任意一个块时,直接索引找到地址进行访问即可。但是当文件很大时,所维护的索引表就会很大,所以有了间接索引表的出现。


间接索引表中有15个索引项,前12个地址存放了12个可直接获取地址访问的直接块,这12个块可保存12*4KB=48KB的文件;

若文件存储所需大于12个块,就需要建立一个新的一级间接索引表,此时第13个索引就会指向一个新的块,其中存放了4kb / 4bytes = 1024个块的地址(块大小为4KB,一个指针大小为4bytes),通过一级间接索引表,可索引的文件大小已经变为 (1024+12) * 4kb ≈ 4M

若文件大小又超过了1024+12=1036个块,就又需要第14个索引来指向一个新的块,该块就是所谓的二级间接索引表,存放了1024个一级间接索引表的地址,每个一级简介索引表可以表示4M的文件,所以如果使用二级间接索引表最多可表示 1024*4M = 4G 大小的文件

同理,当三级间接索引表也使用的时候,最多就可表示 1024*4G = 4T 大小的文件。

结论:ext3文件系统下,当块大小为4k得时候,支持的单个文件大小小最大为 4TB

当然通过这个例子也能够简单的了解下inode是如何访问到对应文件的数据。接下来进入正题。


硬链接

一般情况下,文件名和inode号码是"一一对应"关系,每个inode号码对应一个文件名。但是Unix/Linux系统允许多个文件名指向同一个inode号码。这意味着,可以用不同的文件名访问同样的内容;对文件内容进行修改,会影响到所有文件名;但是,删除一个文件名,不影响另一个文件名的访问。这种情况就被称为"硬链接"(hard link)


命令

ln默认创建硬链接:

  ln 源文件 目标文件

示例

  1. 先创建file.txt文件观察inode信息
[root@suhw ~]# stat file.txt 
  File: ‘file.txt’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 33575038    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2020-09-27 09:53:29.477000000 +0800
Modify: 2020-09-27 09:53:29.477000000 +0800
Change: 2020-09-27 09:53:29.477000000 +0800
 Birth: -
  1. file.txt创建硬链接hardlink
[root@suhw ~]# ln file.txt hardlink
  1. 分别打印源文件和目标文件的inode信息
[root@suhw ~]# stat file.txt 
  File: ‘file.txt’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 33575038    Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2020-09-27 09:53:29.477000000 +0800
Modify: 2020-09-27 09:53:29.477000000 +0800
Change: 2020-09-27 15:38:07.529000000 +0800
 Birth: -
 
[root@suhw ~]# stat hardlink 
  File: ‘hardlink’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 33575038    Links: 2
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2020-09-27 09:53:29.477000000 +0800
Modify: 2020-09-27 09:53:29.477000000 +0800
Change: 2020-09-27 15:38:07.529000000 +0800
 Birth: -

会发现,添加完硬链接后,只有链接数加了1,剩下的所有内容都保持不变

  1. 删除源文件,观察硬链接文件
[root@suhw ~]# rm -rf file.txt 
[root@suhw ~]# stat hardlink 
  File: ‘hardlink’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 33575038    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2020-09-27 09:53:29.477000000 +0800
Modify: 2020-09-27 09:53:29.477000000 +0800
Change: 2020-09-27 15:42:29.895000000 +0800
 Birth: -

此时会发现删除文件,只会将链接数减1,当链接数为0时,系统就会回收对应的block


软链接

软连接就如同windows中的快捷方式,虽然文件A和文件B的inode号虽然不一样,但是文件A的内容是文件B的路径。读取文件A时,系统会自动将访问者导向文件B。因此,无论打开哪一个文件,最终读取的都是文件B。这时,文件A就称为文件B的"软链接"(soft link)或者"符号链接(symbolic link)

这意味着,文件A依赖于文件B而存在,如果删除了文件B,打开文件A就会报错:“No such file or directory”。这是软链接与硬链接最大的不同:文件A指向文件B的文件名,而不是文件B的inode号码,文件B的inode"链接数"不会因此发生变化。


命令

通过ln -s命令可以创建软链接。

 ln -s 源文文件或目录 目标文件或目录

示例

  1. 新建file.txt并查看inode信息
[root@suhw ~]# stat file.txt 
  File: ‘file.txt’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 33575038    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2020-09-27 15:49:09.338000000 +0800
Modify: 2020-09-27 15:49:09.338000000 +0800
Change: 2020-09-27 15:49:09.338000000 +0800
 Birth: -
  1. 创建软链接
[root@suhw ~]# ln -s file.txt softlink
  1. 对比软链接文件和源文件的inode信息
[root@suhw ~]# stat file.txt 
  File: ‘file.txt’
  Size: 0         	Blocks: 0          IO Block: 4096   regular empty file
Device: fd00h/64768d	Inode: 33575038    Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2020-09-27 15:49:09.338000000 +0800
Modify: 2020-09-27 15:49:09.338000000 +0800
Change: 2020-09-27 15:49:09.338000000 +0800
 Birth: -
[root@suhw ~]# stat softlink 
  File: ‘softlink’ -> ‘file.txt’
  Size: 8         	Blocks: 0          IO Block: 4096   symbolic link
Device: fd00h/64768d	Inode: 33575039    Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Context: unconfined_u:object_r:admin_home_t:s0
Access: 2020-09-27 15:49:49.162000000 +0800
Modify: 2020-09-27 15:49:36.821000000 +0800
Change: 2020-09-27 15:49:36.821000000 +0800
 Birth: -

会发现创建软链接并不会增加源文件的链接数,并且inode号也不相同

  1. 删除源文件,查看软链接文件
[root@suhw ~]# rm -rf file.txt 
[root@suhw ~]# cat softlink 
cat: softlink: No such file or directory

验证了之前所说的,由于已经删除了源文件,当我们通过软链接再访问源文件时,就会报已经没有对应文件了。

  1. 在当前目录重新新建file.txt,再次打开软链接文件
[root@suhw ~]# touch file.txt
[root@suhw ~]# cat softlink 
[root@suhw ~]# 

又证实了软链接存储的是目标文件的路径。


补充

通过inode号删除文件

有时,文件名包含特殊字符,无法正常删除。这时,直接删除inode节点,就能起到删除文件的作用。

[root@suhw ~]# ll -i
33575038 -rw-r--r--. 1 root root    5 Sep 28 10:53 file.txt
[root@suhw ~]# find ./* -inum 33575038 -delete

此时就会发现通过匹配inode号我们删除了file.txt文件

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值