硬链接与符号链接

December 09, 2023
测试
测试
测试
测试
3 分钟阅读

【环境】

虚拟机VirtualBox

Ubuntu20虚拟机上有2块硬盘

一个30G大小, 一个10G大小

【分区,格式化,挂载】

启动Ubuntu20虚拟机后, 使用 fdisk -l 查看磁盘信息

接下来对10G的硬盘进行分区,格式化,挂载.

fdisk /dev/sdb

【1】输入n 表示添加一个新的分区

【2】输入p表示分区类型是主分区

【3】输入1表示这个主分区是磁盘的第一个分区

【4】default 2048表示这个主分区的起始扇区是2048

【5】+5120M 表示这个主分区大小是5120M = 5G, 我们把这个10G的磁盘先拿出来5G作为第一个主分区

【6】输入w表示分区信息持久化

再次使用fdisk -l查看磁盘信息,就可以看到刚才的分区了

分区完成之后, 紧接着就是对这个新的/dev/sdb1分区进行格式化.

mkfs -t ext3 -c /dev/sdb1

格式化完成之后, 紧接着就是挂载, 将这个分区挂载到某个目录下, 我们挂载到/mnt目录下

使用df -TH 查看

信息都是正确的

但是,一旦重启机器, 挂载信息就不存在了, 因此还需要修改一下/etc/fstab文件, 新增一条关系记录

环境搭建完成

【创建硬链接和符号链接】

给read_disk.py文件创建硬链接和符号链接.

ln read_disk.py sl_read_disk.py

硬链接

ln -s read_disk.py sl_read_disk.py

软链接

同时查看下这3个文件的inode值

最左侧表示每个文件的inode值, 可以看出来, 硬链接文件与原文件的inode值相同, 软链接文件生成了新的inode值.

使用stat命令分别查看三个文件信息

可以看到原文件和硬链接文件的信息是一样的, 而软链接的信息就是不同的.

而且软链接的内容大小是12, 这12个字符是什么信息呢? 也就是说软链接sl_read_disk.py文件里面存储的是什么?

我们可以数一下软链接指向的原文件名称的字符数,正好是12字符, 难道是巧合?

而且我们还发现一个问题

软链接占用的磁盘空间居然是0, 明明实际大小是12, 怎么会不占用磁盘块呢? 不敢相信. 其实这是操作系统的优化, 因为这个软链接只有12个字符大小, 操作系统虽然默认会给每个文件至少分配4K大小的空间, 但如果给这个软链接分配4K大小空间, 几乎是浪费了4K的空间, 因此当文件很小的时候, 文件的实际内容是与元信息存储在一起的.

文件的信息分为元信息和实际数据两个部分, 我们使用stat看到的都是元信息

假如我们创建一个文件名称大于60个字符的文件, 然后给它创建一个软链接那么就会看到软链接占用了磁盘块.

我用的Ubuntu20只有文件名称大于等于60个字符, 软链接文件才会占用磁盘块

创建012345678901234567890123456789012345678901234567890123456789.c文件,并给它创建了一个软链接文件 number_sl.c 查看软链接文件元信息, 显示占用了8个磁盘块

每个磁盘块默认512字节

这个number_sl.c软链接文件大小是62字节, 我们就看下这个62字节是什么内容.

首先查看下number_sl.c所在的挂载点

stat --format=%m number_sl.c

查看挂载点所在的分区

dubug指定的/dev/sda5分区

debugfs /dev/sda5

如上图, 软链接number_sl.c文件中存储的就是原文件的名称, 也就是使用ln -s 012345678901234567890123456789012345678901234567890123456789.c number_sl.c 命令创建软链接的原文件名称.

总结: 软链接占用实际的磁盘块空间, 软链接中存储的是原文件名称

接下来我们把软链接都删除, 只保留原文件和硬链接, 以及再新增一个1.txt文件

通过ll 命令查看文件大小共计20K. 然而你现在看到的都不是真实的.

首先1.txt文件内容我只写了4个字符, 所以它实际大小4个字节, 但是霸占了4K的磁盘空间, 因为操作系统默认会给每个文件至少分配4K大小空间. read_disk.py是原文件, 也会霸占4K的磁盘空间. 而硬链接指向的是原文件, 硬链接并没有占有实际的磁盘空间, 但是ll命令在统计大小的时候, 不会在意这些的, 虽然原文件和硬链接都执向同一个文件, 实际只占有4K磁盘空间, 但是ll命令依然按照4K+4K来统计大小.

我们使用du -h 命令统计的才是实际占有磁盘块大小空间

实际上只有当前目录占有4K, 1.txt文件占有4K, 原文件read_disk.py占有4K的磁盘块空间, 所以实际是12K,并非ll命令统计的20K. 毕竟这两个命令站在的角度不同, 看待`问题`的结果也不同.

总结: 硬链接不会占用磁盘块, 它指向原文件

再来看一个情况, 如下图

文件大小40984个字节, 文件占用磁盘大小16*512=8192个字节. 文件的实际大小居然比装它的所有磁盘块的和还大, 这是本文中第二种遇到的size > 磁盘块的情况了. 而这里说的这种情况是因为这个3.txt文件是个空洞文件, 也就是说文件头尾有数据, 中间大片空间都是没有数据的.

使用命令od -c 3.txt 查看文件内容, 文件头部有www.infuq.com信息, 尾部有个字符v, 文件中间没有任何数据.

网上之前看过一篇文章, 大概就是说某个文件大约几个G大小, 可以删除那个文件一下子就删除了. 根本原因就在于那个文件是个空洞文件. 使用ll命令看文件大小貌似很大, 但是ll命令欺骗了我们, 实际文件大小很小, 使用du命令看到的大小才是真实的.

之前还在网上看过一篇文章说, 一个数据库文件几百G, 怎么可以很快把它删除掉. 也是运用了硬链接的原理,给文件创建一个硬链接, 然后就可以把原文件删除了. 其实删除原文件也只是把原文件的元信息删除掉,实际的数据块并没有被删除, 因为硬链接还指向着数据块, 这也是运用硬链接解决删除大文件的原理.

在文章一开始我们新增了一个分区, 现在就可以派上用场了. 上面的实验说明都是在同一个目录下创建软链接和硬链接, 也就是说它们都属于同一个磁盘同一个分区.

现在, 原文件还是这个原文件read_disk.py 接下来我要在新的/mnt挂载点对应的/dev/sdb1分区创建硬链接和软链接.

创建硬链接失败

创建软链接成功

总结: 软链接可以跨分区创建, 硬链接不可以跨分区创建

即便两个分区是相同的文件系统也不可以跨分区创建硬链接, 是机制不允许, 并不是文件系统的区别.

继续阅读

更多来自我们博客的帖子

如何安装 BuddyPress
由 测试 December 17, 2023
经过差不多一年的开发,BuddyPress 这个基于 WordPress Mu 的 SNS 插件正式版终于发布了。BuddyPress...
阅读更多
Filter如何工作
由 测试 December 17, 2023
在 web.xml...
阅读更多
如何理解CGAffineTransform
由 测试 December 17, 2023
CGAffineTransform A structure for holding an affine transformation matrix. ...
阅读更多