磁盘与文件系统

目录

一、磁盘

磁盘结构

[​编辑 ​编辑​编辑](#编辑 编辑编辑)

如何定位扇区

CHS地址和LBA地址

二、文件系统

块和分区

inode--索引节点

三、ext2文件系统

[超级块(Super Block)](#超级块(Super Block))

块组描述符表(GDT)

[块位图(Block Bitmap)](#块位图(Block Bitmap))

[inode 位图(Inode Bitmap)](#inode 位图(Inode Bitmap))

[i 节点表(Inode Table)](#i 节点表(Inode Table))

[数据区(Data Block)](#数据区(Data Block))

全局分配特性

在ext2角度看待文件增删查改

增删

查改

inode和datablock映射

各级间接块索引表指向的大小

文件与目录名

路径缓存

格式化与挂载


一、磁盘

磁盘是计算机核心的磁性外存储设备,以磁性介质为载体记录数据,属于非易失性存储(断电后数据不会丢失),是计算机长期存储数据的核心 "仓库"。虽然当前笔记本主流存储设备是固态硬盘SSD,但机械磁盘依靠成本低,容量大依旧是组装服务器的首选。

且磁盘结构与Linux底层文件管理系统强相关,学习磁盘有助于Linux学习。

磁盘结构

磁盘中往往存在多个盘片,在每个盘片上以转轴为中心有多个半径不同的圆环--磁道,每个磁道又是以多个扇区组成。扇区上的磁性代表着01机械码,也就是存储数据。

最经典的每个扇区能存储512字节数据(当然也有4k版本),当转轴高速转动的时候读写磁头会有规律的摆动,当探测到目标扇区后会进行对应的读写操作。

扇区是从磁盘读出和写入信息的最小单位,通常大小为 512 字节。

  • 磁头(head)数:每个盘片一般有上下两面,分别对应 1 个磁头,共 2 个磁头
  • 磁道(track)数:磁道是从盘片外圈往内圈编号 0 磁道,1 磁道......,靠近主轴的同心圆用于停靠磁头,不存储数据
  • 柱面(cylinder)数:磁道构成柱面,数量上等同于磁道个数
  • 扇区(sector)数:每个磁道都被切分成很多扇形区域,每道的扇区数量相同
  • 圆盘(platter)数:就是盘片的数量
  • 磁盘容量 = 磁头数 × 磁道 (柱面) 数 × 每道扇区数 × 每扇区字节数

我们要注意将柱面与圆盘分别开来,柱面是统一半径,各圆盘上的磁道总称,柱面不是单指某一个圆盘。

如何定位扇区

要定位一个扇区,首先需要确定其所在哪个柱面,再确定在哪个盘面上(各读写磁头是共进退的),最后确定在哪个扇区。在逻辑上就是一个三维数组。

回想过去常见的二维数组,我们要定位二维数组中的元素是通过行和列两步分别确定的。在磁盘上的定位逻辑与此相同(都是多维数组)。在之前C语言基础上,我们统一将多维数组看成线性结构。

在磁盘中定位扇区,步骤是:1.先定位所处柱面,2.再定位所处盘面,3.最后定位扇区

为什么先定位柱面?

首先磁盘上的多个读写磁头是共进退的(固定在同一转轴上),如果第一步判断所处盘面就会导致读取效率最慢的判断柱面/磁道动作需要执行两遍,效率远不如第一步判断柱面。

CHS地址和LBA地址

CHS(Cylinder-Head-Sector,柱面 - 磁头 - 扇区)是早期磁盘的物理寻址方式,而 LBA(Logical Block Address,逻辑块地址)是现代操作系统(包括 Linux)使用的线性寻址方式,两者本质是对同一物理扇区的不同编号方式。

说明白点CHS地址是三维的,而LBA地址是一维线性的。Linux采用LBA地址模式。

在Linux中,磁盘的存储容量会被视为对应容量的一维数组,下标从0开始。对于如何具体管理区分不同磁道、盘面、扇区则会由一套算法进行CHS地址和LBA地址之间的转化:

Linux会自动处理CHS和LBA地址之间的转化,并不需要我们进行额外处理。CHS和LBA的设计目的就是为了将硬件底层与操作系统解耦,当扇区存储大小为4k时仅需要改变转化算法,而不需要从头设计设配的数据结构。

二、文件系统

块和分区

磁盘上的扇区很多,如果读取文件需要一个个读取扇区就很慢,为了提升效率Linux系统将多个扇区组合到一起,这个由多个扇区组成的结构被称为"块"。

一个块的大小是在格式化的时候就确立的,不能被更改。一般是8个扇区为一块,存储空间为512*8=4096字节=4kb。

块是文件存储的最小单位。

电脑上通常分有C盘D盘分区,磁盘上的分区结构也主要是为了把整块物理磁盘的存储空间做「逻辑隔离与精细化管理」,解决「整盘使用的各种痛点」。最常见的就是C盘D盘的分区就是为了防止普通文件过多占用系统盘导致卡顿崩溃。

inode--索引节点

文件=内容+属性,我们使用ls和stat指令能获取文件的属性信息

因为文件都是存储在块中的,每个文件的属信息也是如此。Linux文件的属性和内容是分开存储的,保存文件属性的集合叫做inode,一个文件,一个inode形成映射关系。inode内有一个唯一的标识符,叫做inode号。

值得注意的是,文件名这一属性并没有纳入到inode数据结构中,而是存放在路径下。inode数据结构一般大小为128字节或256字节,不同文件之间的存储内容大小可能不同但文件的属性大小一定相同。

三、ext2文件系统

文件要存储在磁盘上时,需要先在磁盘上格式化为某种文件系统,这样才能存储文件。而ext2文件系统就是Linux上的经典文件系统。

如上图所示,ext2文件系统将磁盘各分区划分成一个个块组

超级块(Super Block)

超级块中存储的是整个文件系统的全局元数据,包括总块数、inode 总数、块大小、inode 大小、文件系统版本、挂载时间、最后检查时间、空闲块数 / 空闲 inode 数等核心信息。超级块是文件系统的 "总控信息库",对文件系统的完整性至关重要;为防止单点故障,除块组 0 存储主超级块外,还会在多个关键块组(如 1、3、7、15 等)中保存备份拷贝,便于文件系统损坏后的恢复。

块组描述符表(GDT)

块组描述符表用于逐一描述每个块组的关键信息,包括该块组的块位图、inode 位图、inode 表的磁盘起始块号,以及块组内空闲块数、空闲 inode 数、已用目录项数等状态信息。整个分区中有多少个块组,就对应多少个块组描述符;这些描述符连续排列组成 GDT,且 GDT 会随超级块一同在多个块组中备份,确保块组信息可恢复。

块位图(Block Bitmap)

块位图是每个块组专属的元数据,以二进制位为最小单位,每一位对应数据区中的一个文件系统块:位为 1 表示该块已被占用(存储数据),位为 0 表示该块空闲可分配。块位图通常占用 1 个文件系统块,系统可通过扫描块位图快速找到空闲数据块,是数据块高效分配 / 回收的核心依据。

inode 位图(Inode Bitmap)

inode 位图是每个块组专属的元数据,为一整块连续的字节(通常占 1 个文件系统块,如 4KB);其中每一个二进制位对应块组内的一个 inode:位为 1 表示该 inode 已被文件 / 目录占用,位为 0 表示该 inode 空闲可分配。系统通过 inode 位图可快速定位空闲 inode,完成文件创建时的 inode 分配。

i 节点表(Inode Table)

i 节点表是每个块组的核心元数据区域,存放该块组内所有 inode 的完整属性,包括文件大小、所有者 UID / 所属组 GID、文件权限、访问时间 / 修改时间 / 属性修改时间、数据块指针、硬链接数等。i 节点表是当前块组所有 inode 属性的集合;inode 编号以 "整个分区" 为单位从 1 开始全局连续划分(0 号 inode 保留),不同块组的 inode 编号无重叠,且绝对不可跨分区。

数据区(Data Block)

数据区(Data Block)是每个块组中用于存放文件实际数据内容的区域,如文本、图片、视频、程序代码等,也是文件系统中占用空间最大的存储区域;数据区以文件系统块为最小分配单位(常见大小为 4KB),即使文件仅 1 字节,也会占用 1 个完整块。数据区中每个块的空闲与已使用状态由块位图(Block Bitmap)进行标记;普通文件的数据区存储实际内容,目录文件的数据区则存储其下所有文件的 "文件名 - 对应 inode 编号" 映射关系;数据块分配以块组为单位管理,系统优先在文件所属 inode 所在的块组内分配数据块,减少磁盘寻道开销。

全局分配特性

在同一个分区内部的 Ext 文件系统中,inode 总数、数据块总数在文件系统格式化阶段就已固定,是提前规划设计好的,不会随文件的创建、删除等操作动态增减。

inode 编号和数据块编号均以整个分区为单位全局有效,而非仅在所属块组内有效。

数据区作为存储文件实际数据的核心区域,其空间范围是整个分区级别的全局有效,块组只是文件系统为提升管理效率划分的逻辑单元,不改变数据区的全局属性。

在ext2角度看待文件增删查改

增删

对于新建文件而言,系统会先在 inode 位图中查找空闲 inode 并分配,将其标记为已使用;接着初始化(也可以称为格式化)该 inode 的文件属性(大小、所有者、修改时间等),再通过块位图分配空闲数据块,将文件实际数据存入数据区;最后在所属目录中记录文件名与对应 inode 编号的映射关系,完成文件创建。

如果要删除文件,只需清除目录中该文件的文件名 - inode 映射,将文件对应的 inode 在 inode 位图中标记为空闲(即注销 inode),同时通过块位图回收文件占用的数据块,被释放的 inode 与数据块空间即可被后续文件重新使用。

查改

在 Linux 上使用指令时可直接用指令名而无需带路径,是因为环境变量保存了指令的搜索路径;我们访问文件时常只需使用文件名,核心原因是目录会存储其下所有文件的文件名--inode 编号映射关系。

查询文件时,系统通过文件名找到对应 inode,再从 inode 中读取文件属性、定位数据块位置,进而获取文件实际数据;修改文件时,若修改内容则更新数据区数据,并同步修改 inode 内的文件大小、修改时间等属性,若修改权限、所有者等属性,则直接更新对应 inode 中的相关字段即可。

inode和datablock映射

如上图所示,inode节点中存在一、二、三级间接块索引表指针和12个直接块指针。当datablock中存储的内容比较小时,可直接使用12个直接块指针指向一个块来存储数据。

当数据较大时则可以使用一、二、三级间接块索引表指针,一级间接块索引表指针中有4个块,每个块分别指向另一个块用于存储数据。

二级间接块索引表指针同样指向是4个块,但每个块指向一级间接块索引表指针。三级间接块索引表指针也指向4个块,但这4个块分别指向二级间接块索引表指针。

各级间接块索引表指向的大小

指针类型 可寻址数据块数 可寻址空间 总容量
直接指针 12 48KB 48KB
一级间接 1024(32位下指针为4字节) 4MB 4MB+48KB
二级间接 1024² = 1,048,576 4GB 4GB+4MB+48KB
三级间接 1024³ = 1,073,741,824 4TB 4TB+4GB+4MB+48KB

所以一般而言不用担心文件太大存不下的情况(当然磁盘空间要富裕)。

文件与目录名

Linux下目录也是文件的一种。

既然我们进行文件操作的时候需要对应的inode编号,那为什么我们使用文件名就可以进行文件操作,这是因为目录文件保存的内容是目录下的文件名+inode映射关系。

所以说要进行文件操作,必须打开对应目录。

路径缓存

严格来说,Linux下不存在专门的目录,Linux下一切皆文件,文件=内容+属性。

如果要进行一个文件操作,原则上必须从根目录开始依次向下找到文件,但这样太慢,所以Linux中有一个数据结构struct dentry 专门用来维护树状路径结构。

每个文件都包含一个denty,denty树状结构整体构成了Linux的路径缓存结构,打开访问任何文件,都在先在这棵树下根据路径进行查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry结构,缓存新路径。

格式化与挂载

格式化是在磁盘分区上创建文件系统的元数据结构如inode表,经过格式化后的文件系统是不能直接使用的,还需要挂载。

所谓挂载就是把一个文件系统(分区)关联到文件系统树中的某个目录,这样才能进行文件操作。

格式化=创建一个仓库,挂载=在仓库上安装门。

相关推荐
groundhappy1 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕1 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫3 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生3 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.114 小时前
linux基础IO
linux·运维·服务器
BelongPanda6 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯6 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_777998347 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器
yunwei377 小时前
eBPF 教程:检查 exec 后真正安装的可执行镜像
linux·开源
笑锝没心没肺7 小时前
yum update 报错:GPG key retrieval failed: [Errno 14] HTTPS Error 404 - Not Found
linux·运维·服务器