首先,我们要理解的一个概念是:什么是链接?

链接是一个传送门。当你使用 vim 打开一个链接的时候,看到的内容是链接所指向的内容。当你使用 cat 后面加一个链接的时候,实际打印的也是链接所指向的内容。linux 为我们屏蔽了很多细节,让我们感觉,操作链接,好像是在操作原始文件一样。

既然如此,为什么还区分硬链接和软链接?它们的区别在哪里?


1 回忆 dir_entry

如果你不知道什么是 dir_entry,请复习 《文件系统初探》、《ext2 文件系统》、《ext2 文件系统实验》,并完成相关的实验。

一路读过来,相信你对文件系统底层已经比较了解,起码你得知道什么是 dir_entry(目录项),什么是 inode。本质上,他们都是结构体,只不过是有组织的保存在物理磁盘上。

本质上讲,目录也只不过是个文件而已,只是一个比较特殊的文件。之前在学 st_mode 的字段 的时候,我们就知道它的高4位就描述了文件的类型,其中就包括普通文件、目录文件、字符设备文件等等。

目录文件中存储的内容,就是一个个的 dir_entry 结构体。这很重要。

在 ext2 文件系统中,它被定义如下:

struct ext2_dir_entry_2 {__u32   inode;          /* Inode number */__u16   rec_len;        /* Directory entry length */__u8    name_len;       /* Name length */__u8    file_type;char    name[255];    /* File name */
};

时刻记住,目录只是个文件,和普通文件没什么两样。只不过,目录文件专门用来保存一个个的 dir_entry 结构体,或者说,保存的是 dir_entry 结构体数组。


2 回忆 inode 结构体

在 dir_entry 中有一个字段 inode,它保存的是 inode 结构体的索引号。根据这个索引号,就可以找到 inode 结构体的具体位置。这里我不打算把 inode 结构体完整的贴出来,它实在太大,我只引用其中现在我们要用的部分。想要看到完整的请参考《stat 函数 》。

struct ext2_inode {// ... __u16   i_links_count; // 有多少个 dir_entry 结构体引用了它// ...__u32   i_block[EXT2_N_BLOCKS]; // 数据块指针数组,可以根据这个成员来找到真正的的数据。// ...
}

inode 节点最重要的作用就是它的成员 i_block 保存了数据块的指针,根据 i_block 就可以找到真正的数据了。 《ext2 文件系统实验》 就已经完整的演示了如何找到文件的真正数据的。


3 dir_entry 与 inode 结构体分析实验

3.1 实验环境准备

不会使用 ln 命令不要紧,我们先把测试文件建立起来。当你读完后面的内容后,自然就明白了。

  • 搭建环境
$ mkdir link
$ cd link
$ echo hello > test.txt
$ ln test.txt hellotest
$ ln test.txt nihaotest
$ ln -s test.txt /home/allen/learninglinux/filesystem/link/test.txt // 你的全路径可能和我有差异,但这不影响
  • 预览


图 1 实验需要的文件


3.2 实验分析

在图1 中使用了 ll -i 命令可以查看文件的详细内容(-i 选项可以把 inode 编号显示出来),其中第一列表示的是文件的 inode 编号,第 3 列是 inode 结构体中的成员 i_links_count 的值,也就是 inode 引用计数。

首要分析就是 link 目录,记住 link 也是文件。遗憾的是,我们没办法直接观察到 link 这个文件中存储的内容,不过前面的描述中我们已经知道 link 文件中保存的是一个个的 dir_entry 结构体。如此,我们可以自己根据图1分析出 link 文件中的每个 dir_entry 结构体是什么。它的文件内容就是一个大小为 6 的数组:

struct dir_entry entries[6]; // 想想为什么是 6?

这样一来,很容易知道 entries[0] 表示的是. 这个目录(当前目录),entries[1] 表示的是 .. 这个目录(上层目录)。

这里具体分析第 3 个 dir_entry.

entries[3].inode = 1050209; // 占用 4 字节
entries[3].rec_len = 17; // 占用 2 字节; rec_len = 4 + 2 + 1 + 1 + 9 = 17
entries[3].name_len = 9; // 占用 1 字节;
entries[3].file_type = EXT2_FT_REG_FILE; // 占用 1 字节;
entryies[3].name[9] = {'h','e','l', 'l', 'o', 't', 'e', 's', 't'}; // 占用 9 字节

其实到这里大家可以发现,dir_entry 的长度是不固定的,它的长度是由 dir_entry 的第二个成员 rec_len 来描述的,所以前面使用数组来定义可能不太准确,但是为了方便描述问题,大家就当成 dir_entry 的大小是固定的吧。


  • 硬链接

如果分析完 link 文件里所有的 dir_entry,聪明的小伙伴会发现,entries[2] (对应hahatest)、entries[3](对应 hellotest )、entries[4](对应 nihaotest )、entries[5](对应 test.txt) 这三个 dir_entry 结构里的 inode 成员的值全是 1050209。这有很深刻的意义,在哪里?——这三个 dir_entry 结构用的都是同一个 inode 结构体。 单纯的从文件名上看,你根本不知道哪个文件是原始文件,哪个是你创建的链接,不是吗?你看,这三个文件前面的文件类型,没有任何迹象能观察出来,谁真谁假。

到这里,其实硬链接就算搞定了。硬链接的本质就在此,dir_entry 结构体中的 inode 值相同,那么就是硬链接。而 inode 结构体中的i_links_count,就是说有多少个 dir_entry 使用了这个 inode 结构体。从图1 上可以看到,hellotest、nihaotest 和 test.txt 他们的引用计数是 3. 即使不用看图1,你也能推算出来。


  • 软链接

图1中还有一个浅蓝色文字 hahatest 。它的权限位 lrwxrwxrwx 暴露了它是一个符号链接(软链接又称符号链接)。它对应的是 link 文件中的 entries[2]. 它的各个值如下。

entries[2].inode = 1050208; // 占用 4 字节
entries[2].rec_len = 16; // 占用 2 字节; rec_len = 4 + 2 + 1 + 1 + 8 = 16
entries[2].name_len = 8; // 占用 1 字节;
entries[2].file_type = EXT2_FT_SYMLINK; // 占用 1 字节;
entryies[2].name[8] = {'h','a','h', 'a', 't', 'e', 's', 't'}; // 占用 8 字节

这个 inode 值(1050208) 很明显与 direntries[4,5,6] 中的 inode 值(1050209) 不同了。我们很好奇,这个 hahatest 文件里存储的是什么?好在 linux 提供了命令 readlink 让我们可以看到它的内容。

$ readlink hahatest

执行完后显示:

/home/allen/learninglinux/filesystem/link/test.txt

这一串正好有 50 个字符,你不用数了。你在回到图1看看,hahatest 文件的大小,是不是 50.

所以,这就是所谓的软链接。它只是个普通文件,如果文件系统没有把 entries[2].file_type 的值改为 EXT2_FT_SYMLINK 的话,它真的就只是个普通文件。


最后,请允许我从网上盗一张图来描述硬链接,软链接的关系。


图2 硬链接与软链接

4 总结

  • 掌握一切皆文件的哲理,目录是,符号链接也是。
  • 掌握 dir_entry 结构体,它保存在哪里?
  • 熟悉 inode 结构体。dir_entry 如何找到它?
  • 掌握硬链接和软链接底层原理
  • 知道可以 readlink 命令读取软链接文件本身的内容
  • 掌握 ln 命令的使用方法

最后,留一个小小问题。可以创建一个目录的硬链接吗?为什么?

20-硬链接与软链接相关推荐

  1. linux-centos7 常用的基本命令--文件内容查看、硬链接和软链接

    一.文件内容查看 1.cat (由第一行开始显示文件内容) cat [-AbeEnstTuv] [--help] [--version] fileName 参数说明: -n 或 --number:由 ...

  2. Linux文件系统:minix文件系统二进制分析3(硬链接与软链接)

    文章目录 系列博文 硬链接 当前minix文件系统目录结构 创建filelevel2.txt的硬链接文件 创建filelevel2.txt的软链接文件 当前minix文件系统目录结构 hexdump文 ...

  3. linux练习2021-11-2硬链接与软链接计划任务

    任务1:创建硬链接与软链接 1.在/root目录下,删除所有文件和目录,然后再创建文件a1.txt和c1.txt .目录aa和cc 命令:cd           rm    -rf    ./*   ...

  4. 浅谈linux中的硬链接和软链接文件以及ln的使用方法

    在linux系统中有一种文件叫做链接文件,可以为解决文件的共享使用.链接的方式可以分为两种,一种是硬链接(Hard Link),另一种是软链接或者也称为符号链接(Symbolic Link). 一.基 ...

  5. linux硬链接与软链接

    详细文章链接:https://www.cnblogs.com/crazylqy/p/5821105.html (上面这个也是转载的!) 区别: 1.硬链接原文件/链接文件公用一个inode号,说明他们 ...

  6. php 删除硬链接,RHCE系列之文件管理----硬链接和软链接

    Linux 文件系统最重要的特点之一是它的文件链接. 链接是对文件的引用,这样你可以让文件在文件系统中多处被看到. 在 Linux 中,链接可以如同原始文件一样来对待.链接可以与普通的文件一样被执行. ...

  7. 实例讲解Linux系统中硬链接与软链接的创建

    导读 Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link).默认情况下,ln命令产生硬链接.硬链接与软链接的区别从根本上要从Inode节点说 ...

  8. Linux 硬链接和软链接的区别

    硬链接和软链接的区别 Linux 与其他类 UNIX 系统一样并不区分文件与目录:目录是记录了其他文件名的文件.我们知道文件都有文件名与数据,这在 Linux 上被分成两个部分:用户数据 (user ...

  9. 理解 Linux 的硬链接与软链接

    Linux 的文件与目录 现代操作系统为解决信息能独立于进程之外被长期存储引入了文件,文件作为进程创建信息的逻辑单元可被多个进程并发使用.在 UNIX 系统中,操作系统为磁盘上的文本与图像.鼠标与键盘 ...

  10. 硬链接、软链接和inode

    一.inode 在Linux中,"一切皆文件". 唯一标识文件的是inode而非文件名,文件名仅是为了方便人们的记忆和使用,系统或程序通过 inode 寻找正确的文件数据块. 什么 ...

最新文章

  1. console.log()的兼容性
  2. PHP学习笔记-PHP语言基础3
  3. 如何调试NativeSample
  4. Adobe illustrator 调整对象大小 - 连载 11
  5. 小米速度!雷军再祭 All in AIoT 大招!
  6. 为什么不能在scrollview中直接添加一个image,然后使animation.begin()??
  7. javascript创建对象的几种方式
  8. 《信号与系统》解读 第1章 信号与系统概述-6:系统对时域信号的基本运算与基本变换---幅度、加法、乘法、积分、微分、时延、反转、混合
  9. 飞客分析:防止数据二次破坏的保护方法
  10. python视频格式转换命令_音视频格式转换
  11. php青蛙跳井代码,初八葬一青蛙跳井怪穴------行龙点劲!
  12. 广达做微软服务器,微软联手广达布局云计算 称策略是软件加服务
  13. Cocos2dx游戏教程(序):火爆抖音的网红口红机真能扎到口红吗?
  14. TensorFlow 直接可用的 30 个最大的机器学习数据集
  15. 搭建微信小游戏开发环境总结
  16. 国外名校课程视频爆红 网友总结“必杀技”(图)
  17. Air Passengers(time series)
  18. IT公司软件工程师薪水排名
  19. 达芬奇大王的链表贪吃蛇(java)
  20. 谷奥是一个非商业网站,我们欢迎所有的google用户/google爱好者贡献你的一份力量:

热门文章

  1. ffmpeg实现变速播放的两种方案
  2. 拐道交叉的css3动画,CSS3图片翻转动画技术详解
  3. sql server 按拼音分类排序的功能
  4. HTML5+CSS3小实例:炫彩爱心加载特效
  5. Makefile中的一些小知识点,及常用的makefile举例
  6. DocArray 0.21.0版本发布!新增OpenSearch后端存储,支持Redis后端存储的多语言文本搜索!...
  7. JavaScript js如何代码加密绑定域名
  8. 如何手动制作透明的图片相框 可以供android使用
  9. scipy.sparse.vstack
  10. LATEXT导入.sty