【Linux】磁盘文件系统(inode)、软硬链接

文章目录

  • [1. 认识磁盘](#1. 认识磁盘)
    • [1.1 磁盘的物理结构](#1.1 磁盘的物理结构)
    • [1.2 磁盘的逻辑结构](#1.2 磁盘的逻辑结构)
  • [2. 引入文件系统](#2. 引入文件系统)
    • [2.1 EXT系列文件系统的分区结构](#2.1 EXT系列文件系统的分区结构)
    • [2.2 inode](#2.2 inode)
  • [3. 软硬链接](#3. 软硬链接)
    • [3.1 软链接](#3.1 软链接)
    • [3.2 硬链接](#3.2 硬链接)

在讲过了内存文件系统后,我们可以知道文件分为两种:

  • 打开的文件(内存中)
  • 未被打开的文件(磁盘中)

今天我们主要来探讨未被打开的文件。

  • 当文件存储在磁盘中时,如果我要打开它,那我首先要能找到它(通过路径)
  • 既然是这样,那Linux中每一个文件都要有路径
  • 为了更好的进行磁盘级文件的管理,我们必须要有一个磁盘文件系统的东西

那么文件系统是怎么把没有被打开的文件在磁盘上管理起来的呢?

只要它管好了,就可以给我们提供正确的路径,那么我们就可以定位这个文件,在系统层面就可以打开这个文件,进而能够转化到内存中,进行内存文件的管理。

1. 认识磁盘

1.1 磁盘的物理结构

  • 磁盘的结构

磁盘在工作时,主轴会高速旋转,磁头也会左右摆动。

  • 磁盘的存储结构

一个盘片有两面,每一面都可以存数据。多个盘片,相同磁道之间自上而下形成一种逻辑结构:柱面。

  • 磁头在运动过程中不断摆动的本质是:定位磁道或柱面。
  • 磁盘在旋转的时候,目的是让磁道上不同的扇区处在磁头下方,本质是:定位扇区。(扇区是磁盘存储数据的基本单位,一般为512字节,读写时是以512字节为整体,构成一个"块",所以磁盘也叫做块设备)

在linux系统也是可以查到扇区的

  • 磁盘每一个面上都有一个磁头,对应h0-h5;读写哪一个磁头,本质是读写哪一面。
  • 传动臂上的磁头是共进退的。

所以如何定位一个扇区呢?

  1. 先定位柱面(cylinder)
  2. 再定位磁头(head)
  3. 最后定位扇区(sector)

因此,这叫做CHS定址法。

由于文件 = 内容+属性,但它们都是数据,在磁盘中无非就是占据哪几个扇区的问题。那既然我们能定位一个扇区了,那能不能定位多个扇区呢?

1.2 磁盘的逻辑结构

磁带也是磁盘的一种,在磁带圈起来时,就类似一个盘面。将其拉直展开,就可以看成是由扇区为单位组成的数组。

我们可以将磁盘想象成卷起来的磁带,那么就可以将磁盘的某一个盘片上的某一个磁道抽象为线性结构,类似于数组:

这样,每一个扇区,就有了一个线性地址(数组下标)

所以,在系统使用文件的时候,只需要使用数组下标法(LBA),不用关心CHS,但是数组下标又是怎么得到的呢?

由于传动臂上的磁头是同进退的,所以在我们找磁道时,所有的磁头共同移动,对应就找到了一个柱面。

所以,磁盘虽然分了很多面,但是在我们看来,逻辑上磁盘是由n多个柱面组成的。

所以,磁盘的真实情况应该是:

所以,磁盘就可以抽象为一个"三维数组",但是在我们看来,其实它还是一个一维数组

所以,每个扇区都有一个下标,我们叫做LBA(Logical Block Address),其实就是线性地址。

LBA与CHS之间可以互相转换(磁盘的工作)。

当磁盘告诉操作系统磁盘的总容量、扇区大小,那OS一瞬间就可以知道有多少个扇区了。

那么从今往后 ,在磁盘的使用者看来,根本不关心CHS地址,而是直接使用LBA地址,磁盘内部自己转换。

所以,从现在开始,磁盘就是一个元素为扇区的一维数组,数组的下标就是每一个扇区的LBA地址。OS使用磁盘,就可以用一个数字访问磁盘的扇区了。

2. 引入文件系统

2.1 EXT系列文件系统的分区结构

有了上面的知识后,我们知道OS与磁盘进行IO时,就是访问数组下标所对应的扇区,但是扇区512字节有点少,即单次IO的数据量有点少。

为了增加单次IO的数据量,OS与磁盘进行交互时,是以1KB、2KB、4KB、8KB等数据块为单位进行IO的,Linux中选择4KB数据块,一个数据块由8个扇区构成。

所以,在文件系统层面上,它才不管扇区,它IO的基本单位是数据块。
数据块转LBA地址:块号*8 + 1,8

那么我们的磁盘就被抽象成了以块位单位的数组。

如果直接对块进行管理的话,成本太高了。因此将众多块又划分为一个分区,最终磁盘被划分为N个分区,分区之间各自独立。

分区中又划分出了组

分完组之后,只需要对组进行管理就可以。

一个组又分为如下几个区域:

2.2 inode

由于文件 = 内容+属性,属性也是数据,是以结构体的方式构建出来的,该结构体叫做inode(文件对应属性的集合,一般是128字节),所以在磁盘的一个4KB块中,会有32个inode。

在Linux中可以使用ls - i 选项查看一个文件的inode,下方显示出来的信息起始就是inode struct中的内容。

在一个组中,会存在非常多的inode,所以组中就存在一张inode Table,存放组中所有inode,方便管理每一个文件。

Data Blocks中,全都是划分好的4KB块,存放的是文件的内容。

所以,在Linux下,文件的属性和内容是分开存储的。

那通过inode找到文件的属性后,内容是怎么找到的呢? - - 在inode中,存在一个block数组,记录当前inode所占用的data block块,后面讲。

一个组中的区域分布如下:

  • inode table(节点表):存储了每个inode的详细信息,包括文件的大小、权限、时间戳、数据块位置等
  • Data blocks(数据区):存放文件内容,全都是划分好的4KB块
  • inode Bitmap(inode table位图):每个bit位表示inode table中的inode是否被占用。 inode号在inode table中早就设置好了,只是有没有被使用的问题。inode bitmap中的位置与inode table中的位置是一一对应的。
  • Block Bitmap(块位图):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用
  • Group Descriptor Table:块组描述符,描述块组属性信息。例如:每个组的起始inode与block编号。
  • 超级块(Super Block):存放当前分区文件系统本身的结构信息。记录的信息主要有:bolck 和 inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。
    Super Block的信息被破坏,可以说整个文件系统结构就被破坏了。Super Block有多份拷贝,可在损坏时进行修复。

分区格式化的本质:写入空的文件系统。将组中的super block、GDT、data bitmap、block bitmap置为空即可。

关于inode

  1. inode是以分区为单位的,一个分区一套inode。因此不同分区可以有相同inode
  2. inode在分配时,只需要确定当前组起始inode即可

关于block

  1. 块号也是以分区为单位的
  2. 块号在分配时,也只需要确定当前组的起始block编号

在一个组中,我们是如何分配一个inode的呢?

  • 由于inode bitmap的存在,我们只需要在bitmap中找一个可用位置,然后加上当前组inode的起始编号即可。 由于组起始inode的存在,我们就在不同组的起始inode之间就形成了一个区间,所以我们就可以分配为全局且唯一的inode

在一个组中,我们是如何分配一个block的呢?

  • 由于block bitmap的存在,我们只需要在blockmap中找一个可用位置,然后加上当前组block的起始编号即可。 在整个区间中,block号也是全局且唯一的。 当一个组中存储大文件,块不够用时,可以跨组!inode中记录了所有存储文件内容的块

当知道一个inode号或者block块时,只需要在GDT中比对每一个组的起始编号,定位组;然后使用提供的inode号或者block号减去该组的起始编号,即可在位图中找到对应的位置,然后就可以确定inode在inode table的位置。

所以我们就可以确定任意一个块、任意一个组了。


那inode和block是怎么映射的呢?inode中block数组是多大呢?

在ext系列的文件系统中,block数组的大小是15,可是一个块才4KB,总共才60KB,那怎么能行呢?

前12个确实直接指向数据块;后三个则不是,它们3个存的是数据块的编号。

当前组的data block不够用时,是可以跨组的。但不建议这么做,因为一旦跨组访问了,意味所有的块不连续了,磁盘寻址效率也会大大降低。


在上面对文件的所有操作中,都是以inode为前提的,但是inode是怎么得到的呢?我们平时操作文件使用的都得文件名呀!

所以inode是通过文件名找到的,我们在struct inode中也并没有看到文件名的存在,那文件名存在哪里呢?

  • 要弄清楚上面的问题,我们首先要知道,文件有普通文件和目录文件,我们之前谈论的全部都是普通文件,那目录文件又是如何呢?
  • 上面我们已经从文件系统角度认识文件了,所以目录文件也要有属性和内容,那内容中也要有对应的数据块。
  • 目录文件的数据块中存的是什么呢? - - 存文件名和inode的映射关系,二者互为映射
  • 所以,文件名存放在文件所属的目录的数据块中

此时,我们就可以更清楚的认识目录的权限:

  • r:没有读权限,就无法读取目录的data block,也就得不到文件名和inode的映射关系,拿不到inode,你怎么访问文件。
  • w:没有写权限,无法把文件名和inode的映射关系保存到目录的data block中

那我们的文件名又是怎么找到的呢?

要找到一个文件名,首先要打开当前目录,访问当前目录的data block;

可是目录也是文件,也有文件名呀?所以还需要继续向上找,直到根目录。根目录的data block中固定存储了文件名与inode的映射关系。

但是在系统中并不是逆向的,而是正向的。

因为任何一个文件都有路径,在最开始时,系统就按照路径进行查找。

当我访问在同一个目录下的另一个文件时,系统还需要从头再访问一遍磁盘的文件系统吗? - - 不需要了,Linux系统中,会对所访问过的路径进行缓存!会以一个多叉树的结构,将路径缓存在内存中,该结构在内核中叫做 dentry树

所以,系统在查找一个文件时

  1. 先按照路径找到文件所在的目录
  2. 在目录的data block块中,获得文件名与inode的映射关系
  3. 拿着inode,对比磁盘分区的GDT,确定该inode在哪一个分组
  4. 确定分组后,用inode减去该分组的起始inode,确定inode的位置n
  5. 通过inode bitmap核实 n 位置,然后找到inode table中的n位置对应的inode
  6. 通过inode中的block数组,访问对应的数组块。

那inode和进程、文件描述符之间又有什么关系呢?

此时,我们的进程和文件就关联起来了。

那整体上我们应该怎么理解呢?

3. 软硬链接

  • Access 最后访问时间
  • Modify 文件内容最后修改时间
  • Change 文件属性最后修改时间

在之前的学习中,我们直到使用ls -l 命令可以查看文件的属性,可是在文件权限后面的那一列数字,代表的是什么呢?

3.1 软链接

建立软链接的方式:

bash 复制代码
ln -s 被链接的文件名  链接后的文件名

下面我们将它们的inode也显示出来

发现二者的inode并不相同,软链接有自己独立的inode,因此,软链接本质是一个独立的文件。

当我们对被链接的文件与链接后的文件操作时,发现它俩操作的是同一个文件。

删除一个软链接的方式:

bash 复制代码
unlink 链接后的文件名

3.2 硬链接

建立硬链接的方式:

bash 复制代码
ln 被链接的文件名  链接后的文件名

此时我们发现,file-hard.link与file.txt两个文件的inode相同,并且权限后面的那一列数组变成了2,这是什么情况呢?而且如果将file-hard.link删掉,那一列数字又变成了1,那一列数字到底是什么意思呢?

首先,既然二者的inode相同,那么硬链接本质上不是一个独立的文件。

了解软硬链接的创建后,那么该如何理解软硬链接呢?为什么要有软硬链接呢?

  • 理解软硬链接

软链接

  1. 软链接有独立的inode,那么它就有内容和属性。
  2. 内容中,它保存的是目标文件的路径,等同于快捷方式

硬链接

  1. 硬链接不是独立的文件,它本质存储的是指向文件inode的引用,通过共享inode来实现对同一文件数据的访问

文件权限后面对应的那一列数字是什么意思呢?

首先我们知道,文件名并不在inode中保存,它保存在文件所属目录的内容(data block)中,这也就意味着会有多个文件名映射到同一个文件上。

换句话说,一个文件在什么时候才能被系统真正的删除呢?- - 没有任何文件名映射到当前文件的inode时。

在inode内部,存在一个引用计数,来统计有多少个文件名映射到当前inode。
那一列数字,对应的就是当前inode的引用计数的个数,即硬链接数。

  • 为什么要有软硬链接呢?应用场景是什么?

软链接的作用

  1. 通过创建一个指向目标文件或目录的软链接,可以简化对目标文件或目录的访问路径。用户可以通过软链接名来访问目标文件或目录,而不需要输入完整的路径。
  2. 软链接类似于一个文件系统中的"快捷方式",如果目标文件或目录被删除或移动,软链接将变成"死链接"(dangling link),即指向一个不存在的文件或目录。

当我创建了一个目录时,为什么它的硬链接数是2呢?

当我在empty目录中又创建了一个目录时,它为什么又变成3了呢?

因为有以下三个硬链接指向它

  • empty
  • empty/.
  • empty/dir/. .

所以,这就是为什么一个文件创建时,默认有两个隐藏目录 .和 . .,为了方便找路径

硬链接的作用

  1. 数据冗余和备份 :通过创建硬链接,你可以在不同的目录或同一目录中拥有文件的多个访问路径。如果原始文件被删除,硬链接仍然可以访问文件数据。这就意味着,在linux中,如果对文件进行备份,只需要建立硬链接!
  2. 节省磁盘空间:硬链接不会创建文件的副本,而是共享相同的物理数据块。因此,它们可以节省磁盘空间,特别是在需要多个文件副本的情况下。
  3. 文件恢复:如果文件被误删除,但文件系统中仍然存在指向该文件的硬链接,那么文件数据仍然可以恢复。这提供了一种额外的数据保护机制。

注意:Linux中,不允许对目录新建硬链接。因为硬链接后的目录,也是可以进入的,那么就会产生环状路径。

相关推荐
律宏阔5 小时前
WSL Docker 端口明明空闲,但就是绑不上端口
linux·windows
律宏阔5 小时前
WSL 突然断网,无法 ping 内网或外网
linux·windows
穷人小水滴5 小时前
用容器编译 VirtualBox 虚拟机软件 (ArchLinux, podman)
linux·容器·virtualbox
乱码三千6 小时前
如何优雅地直连无公网 IP 的远程 GPU 服务器
linux·人工智能·程序员
yunwei376 小时前
使用 eBPF 跟踪 Nginx 请求
linux·后端·性能优化
yunwei376 小时前
使用 eBPF 跟踪 MySQL 查询
linux·后端·性能优化
yunwei376 小时前
eBPF 示例教程:使用 XDP 捕获 TCP 信息
linux·后端·性能优化
judezh6 小时前
api 容器一直 unhealthy?我把一个 Agent 运行时的健康检查逐条拆了,查出四个问题
运维·docker
GeW6 小时前
制造业高端化,为什么必须重估Linux和数据库?
linux
百万蹄蹄向前冲6 小时前
双端同步!云服务器装最新Node.js v26.10全过程追踪
服务器·人工智能·node.js