磁盘与文件系统

目录

一、磁盘

磁盘结构

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

如何定位扇区

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表,经过格式化后的文件系统是不能直接使用的,还需要挂载。

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

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

相关推荐
Bigbig.1 小时前
Linux 挖矿病毒深度排查与修复实录
linux·安全
GeminiJM2 小时前
LangGraph 源码学习笔记
linux·笔记·学习·langchain
charlie1145141912 小时前
RK3568跑Ubuntu 24.04全路程指南(以正点原子的RK3568开发板为例子)
linux·笔记·ubuntu·rootfs·教程·环境配置·rk3568
MyFreeIT2 小时前
OpenSSL
linux·运维·服务器
瀚高PG实验室2 小时前
hghac8008漏洞扫描处理
linux·网络·windows·瀚高数据库
AD钙奶-lalala2 小时前
Error starting ApplicationContext. To display the condition evaluation···
linux·运维·服务器
71ber2 小时前
RHCSE 实战笔记: LVS 负载均衡集群深度解析
linux·服务器·lvs
Byte不洛2 小时前
TCP 服务器如何支持高并发?单进程、多进程、多线程模型详解
linux·网络编程·高并发·tcp·socket编程
Jia ming2 小时前
Linux内核动态调试技术揭秘
linux·内核动态调试