【Linux系统编程】第二十九弹---深入探索Linux文件系统:从磁盘存储到inode结构与文件操作

✨个人主页:熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】【Linux系统编程】

目录

1、文件系统相关知识

2、磁盘

2.1、理论补充

2.2、看看物理磁盘

2.3、磁盘的存储结构

2.3、对磁盘的存储进行逻辑抽象

3、inode

[2.1、引导块(Boot Block)](#2.1、引导块(Boot Block))

[2.2、块组(Block Group)](#2.2、块组(Block Group))

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

2.4、块组描述符(GDB)

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

[2.6、inode位图(inode Bitmap)](#2.6、inode位图(inode Bitmap))

[2.7、inode节点表(inode table)](#2.7、inode节点表(inode table))

[2.8、数据区(Data Blocks)](#2.8、数据区(Data Blocks))

3、文件系统

3.1、增删查改文件

3.2、理解目录


1、文件系统相关知识

文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构

Linux常见的文件系统类型包括ext2、ext3、ext4。

ext2 :高效稳定,但非日志文件系统

ext3 :基于ext2发展而来,增加了日志功能。提高了文件系统的可靠性和稳定性,特别是在系统崩溃或断电时能快速恢复。

ext4 : 对ext2和ext3进行改进和增强。引入extents数据结构,支持更大的文件和理论上无限的文件数量。增加了flex_bg和sparse_super特性,提升性能。

前面我们学习的都是已经被打开的文件,但是在Linux系统中,存在大部分非常多的文件,只有少部分文件被打开 ,那么没有打开的文件存放在哪里呢?

存放在磁盘中,磁盘也是一种文件,文件 = 属性 + 内容 ,内容和属性都是数据,且都是二进制数据。

磁盘文件怎样存储数据呢?下面我们对磁盘进行深入探讨!!!

注意:Linux中文件的属性和内容是分开存储的。

2、磁盘

2.1、理论补充

当下磁盘的应用场景

1.现在大多数电脑上装的都是SSD了

  • SSD代表固态硬盘(Solid State Drive),是一种使用闪存芯片作为存储介质的电脑存储设备。目前个人电脑或工作站等设备普遍采用SSD作为主要的存储介质。SSD相比传统的机械硬盘(HDD,Hard Disk Drive)有更快的读写速度、更低的功耗和更小的噪音,同时因为没有机械运动部件,所 以更耐震动,故障率也相对较低。

2.公司服务器长时间存储还是使用磁盘

在公司或企业的服务器存储解决方案中,尽管SSD在性能上有明显优势,但出于成本和容量考虑,长时间存储大量数据通常还是使用机械硬盘(HDD)。HDD的成本较低,存储容量较大,适合用来存储那些不经常访问但需要长期保存的数据。

2.2、看看物理磁盘

磁盘

磁盘作为计算机中的机械部件,通常由一个或多个旋转的盘片组成每个盘片有两个面每个面上有一层磁性材料 。通过主轴连接,磁盘上附有磁头。数据存储的基本单位是扇区 (Sector),传统上每个扇区大小为512字节,但近年来逐渐过渡到4096字节的大扇区。

磁盘物理结构

  1. 磁头是一面一个,左右摆动,两个整体移动的,有磁头停靠点
  2. 磁头和盘面不接触 ,所以物理上不适用于笔记本,开机状态移来移去,磁头刮花了磁盘,属于硬件问题
  3. 机械磁盘要在无尘环境下,灰尘落上去可能会把数据都磨没了

磁盘存储

  • 所有的数据都在盘片上以二进制存储,磁头通过充放电写入
  • 内存掉电易失设备,磁盘永久性存储介质
  • 通过充放电/强弱/波,在磁盘上写入 01 数据,像吸铁石的 N S 级
  • 高温消磁
  • 大型互联网公司淘汰磁盘,国家规定不能数据泄露,磁盘擦除并不完全,局部数据的残留也可以被恢复,磁盘上的影子数据也挺危险的,解决方法:和厂商协商,调用接口去除

盘片

硬盘

结论:

1、磁盘是一个机械设备:

  • 这里的"磁盘"通常指的是机械硬盘(HDD,Hard Disk Drive),它是由多个机械部件组成的存储设备。在个人电脑或服务器中,尽管还有其他可能包含机械部件的设备(如光盘驱动器、软盘驱动器等),但在现代计算机系统中,机械硬盘往往是唯一的主要机械存储设备。这是因为其他类型的存储设备,如固态硬盘(SSD)、内存条(RAM)、U盘等,都不包含机械运动部件。

2、也是一个外设:

  • "外设"是外部设备的简称,指的是连接到计算机主机的硬件设备,用于扩展计算机的功能。磁盘(如HDD)作为存储设备,通常被视为计算机的外设,因为它位于计算机主机的机箱外部(或者至少是可分离的),并通过数据传输接口(如SATA、SAS等)与主板连接。尽管它是计算机运行所必需的组成部分,但它并不直接集成在主板上,因此被分类为外设。

2.3、磁盘的存储结构

磁盘的存储结构

  • 磁盘盘片:硬盘存储数据的核心部件,盘片的数量可以从一片到多片不等,通常盘片越多,硬盘的存储容量越大。每个盘片都有两个盘面,即正反两面都可以存储数据。
  • 主轴马达:位于盘片的中心,负责驱动盘片以恒定的速度旋转。转速越高,硬盘的数据访问速度越快。
  • 读写磁头:每个盘片表面都有一个读写头,用于读取和写入数据。读写头悬浮在盘片表面上非常微小的距离内(通常是几十纳米),以避免与盘片接触并造成损害。
  • 臂架:读写头被安装在臂架上,臂架的运动使读写头能够在盘片的半径方向上移动,从而访问盘片上不同轨道的数据。

数据存储原理

  • 磁道与扇区:每个盘面被划分为多个磁道,这些磁道是同心圆环,从外围开始编号。每个磁道又被划分为若干个扇区,扇区是磁盘的最小组成单元,通常是512字节或4KB(高级格式化)。扇区是硬盘的最小存储单元。
  • CHS定位法:硬盘通过CHS(Cylinder/Head/Sector)定位法来定位数据。即定位在哪一个磁道(Cylinder)、使用哪一个磁头(Head)以及定位在哪一个扇区(Sector)。
  • 数据写入:当计算机需要将数据写入磁盘时,首先将待存储的数据传输给磁盘控制器。磁盘控制器再将数据传输给磁头。磁头通过在磁盘表面上产生磁场来磁化磁盘表面上的磁性材料,从而存储数据。这些磁区可以通过改变磁盘表面上的磁极方向,表示不同的数据位。
  • 数据读取:当计算机需要读取磁盘上的数据时,磁盘控制器会指示磁头移动到包含所需数据的磁道上。磁头会定位到具体的扇区上,并检测该扇区中的磁场变化。通过将磁场变化转换为数字信号,磁头将读取的数据传输给磁盘控制器,进而传输给计算机进行处理。

如何找到一个指定位置(任意位置)的扇区?

1、找到指定的磁头 Header

2、找到指定的磁道(柱面) Cylinder

3、找到指定的扇区 Sector

上面的查找方式为CHS定址法

文件实际就是在磁盘中占有几个扇区的问题!!!

2.3、对磁盘的存储进行逻辑抽象

使用磁带来进行类比!!!

将一个圆延展开来进行扇形分区(struct 来实现):存储 LBA 信息

随着技术发展,出现了逻辑块地址(LBA) 的概念,它可以解决CHS寻址的局限性。LBA将磁盘上的所有扇区视为一个线性序列,操作系统可以通过LBA直接定位到扇区,而无需关心具体的磁头、柱面和扇区信息。

磁盘对扇区一视同仁的划分,管理好了 10 G 的一个扇形,就能管理好 800 G-- 分治的思想 化大为小 。

3、inode

文件系统不仅需要存储文件内容,还需要存储文件的元数据,如文件大小、所有者、权限等。这些元数据存储在索引节点(inode)中。

为了能解释清楚inode我们先简单了解一下文件系统

Linux ext2文件系统,上图为磁盘文件系统图 (内核内存映像肯定有所不同),磁盘 是典型的块设备,硬盘分区被划分为一个个的block。一个block的大小是由格式化的时候确定的,并且不可以更改。例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。而上图中启动块(Boot Block)的大小是确定的。

2.1、引导块(Boot Block)

  • 引导块(Boot Block) 是文件系统中的一个特殊块 ,用于**存储磁盘分区信息和启动信息。**通常位于分区的第一个块,其大小通常为1KB,这是由PC标准规定的。

功能与作用

  • 存储引导加载程序:Boot Block中存放的是boot loader(引导加载程序),这段程序在开机启动时被加载,用于引导操作系统的启动过程。
  • 系统启动的关键:Boot Block对于操作系统的启动至关重要。如果Boot Block中的数据有误或丢失,操作系统可能无法启动。

与Linux文件系统的关系

  • 文件系统结构:Linux文件系统(如ext2、ext3、ext4等)会将磁盘划分为多个Block Group(块组),但Boot Block是独立于这些块组之外的特殊区域。
  • 数据组织:虽然Boot Block不直接参与文件数据的存储,但它确保了系统能够正确地启动并加载操作系统,从而进一步访问和管理存储在磁盘上的文件和数据。

Bootblock Linux的特殊说明

  • Bootblock Linux:这是一个适用于嵌入式设备和嵌入式系统的轻量级Linux操作系统。其引导块(bootblock)是该系统启动的核心组件之一,采用了精简的设计和优化的代码,以减少启动时间和资源消耗。
  • 应用场景:Bootblock Linux非常适合于资源有限的设备,如路由器、智能家居设备和物联网设备等。

总结

Boot Block是Linux文件系统中一个关键且特殊的区域,它存储了引导加载程序,对于操作系统的启动至关重要。了解Boot Block的功能和作用有助于更好地理解Linux文件系统的整体结构和启动过程。同时,对于特定于嵌入式系统的Bootblock Linux来说,其引导块的设计和优化更是体现了其在资源受限环境下的高效性和稳定性。

2.2、块组(Block Group)

  • 块组(Block Group) :是Linux文件系统中的一个逻辑单元 ,用于组织和管理磁盘上的数据块(Blocks)和inode节点。ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组成。政府管理各区的例子。

2.3、超级块(Super Block)

  • 超级块(Super Block)存放文件系统本身的结构信息。以下是一些典型的Super Block内容:
  • 文件节点(inode)计数:记录文件系统中inode的总数、已用数和空闲数。inode是存储文件元数据(如权限、所有者、大小、时间戳等)的数据结构。
  • 块(block)计数:记录文件系统中块的总数、已用数、空闲数和保留数。块是文件系统中存储文件数据的基本单位。
  • 块大小和块组:指定块的大小以及文件系统被划分为多少个块组(block group)。每个块组包含一定数量的块、inode和Super Block的备份(如果有的话)。
  • 时间戳:记录文件系统最后一次被挂载、写入和检查的时间。
  • 状态标志和错误处理:记录文件系统的当前状态以及遇到错误时的处理策略。

Super Block是文件系统中不可或缺的组成部分,由于Super Block对文件系统的重要性,许多文件系统都提供了Super Block的备份机制。

2.4、块组描述符(GDB)

  • 块组描述符(Group Descriptor Table,GDB)描述块组属性信息,如块组的状态、位置等。它通常包含了关于该块组的元数据,如:
  • 块组中数据块的数量和状态(已用、空闲等)。
  • inode的数量和状态。
  • 块位图和inode位图的起始位置。
  • 可能的块组和inode表的起始位置。
  • 其他与块组管理相关的参数。

块组描述符的作用在于提供对块组内数据和元数据的快速访问和管理。通过读取块组描述符,文件系统可以快速确定块组中哪些数据块和inode是可用的,哪些已经被占用,从而有效地进行文件数据的读写和元数据的管理。

2.5、块位图(Block Bitmap)

  • 块位图(Block Bitmap) :是一种位图数据结构,记录inode节点的使用情况,即哪个数据块已经被占用,哪个数据块没有被占用。

功能

  • 空间管理:块位图使得文件系统能够快速地查找空闲的存储块,以便为新文件或目录分配空间。同时,它也能快速确定哪些存储块已被使用,从而避免数据覆盖等错误。
  • 性能优化:通过块位图,文件系统可以减少对存储介质的访问次数,提高数据读写效率。例如,在分配新空间时,只需扫描块位图即可找到空闲块,而无需遍历整个存储介质。

2.6、inode位图(inode Bitmap)

  • inode位图(inode Bitmap) :inode位图是一个位数组(bit array,记录inode节点的使用情况,即每个bit表示一个inode是否空闲可用。

作用

  • inode管理:inode位图使得文件系统能够快速地查找空闲的inode,以便为新文件或目录分配inode。同时,它也能快速确定哪些inode已被使用,从而避免inode的重复分配。
  • 空间优化:通过inode位图,文件系统可以更有效地管理inode空间,减少空间的浪费。
  • 性能提升:在文件系统的操作中,inode的分配和释放是常见的操作。inode位图通过提供快速的查找和更新能力,提升了这些操作的性能。

2.7、inode节点表(inode table)

  • inode节点表(inode table) :存放文件属性,如 文件大小,所有者,最近修改时间等。

Linux中文件的属性是一个固定大小的集合。

复制代码
struct inode
{
    int size; // 文件的字节数:表示文件的大小,即文件包含的数据量。
    mode_t mode; // 权限掩码
    int creater; // 文件创建者
    int time; // 文件的时间戳,ACM时间
    ...
    int inode_number;// inode 编号
    int datablocks[N];
}
  1. 该集合大小为128字节。
  2. inode内部不包含文件名!
  3. 内核层面,每一个文件都要有inode number!
  4. 我们通过inode编号标识一个为文件!
  5. 一个正常文件,一个inode集合!

stat

将显示指定文件或目录的详细信息。

语法

复制代码
stat [选项] 文件或目录

常用选项:

  1. -c, --format=<格式> :指定自定义格式输出文件信息。在格式字符串中,可以使用特殊转义序列来指定要显示的信息,如%n(文件名)、%s(文件大小)、%y(最后访问时间)等。

  2. -f, --file-system:显示文件所在文件系统的信息,包括文件系统的名称、挂载点、类型、大小、可用空间等。

  3. -L, --dereference:显示符号链接的原始文件信息,而不是符号链接本身的信息。

  4. -t, --terse:以紧凑格式输出文件信息,便于快速查看。

  5. -x, --xml:以XML格式输出文件信息,便于程序处理和解析。

ls -i命令也可以查看inode编号。

2.8、数据区(Data Blocks)

  • 数据区(Data Blocks)存放文件内容。文件内容被分割成多个块,存储在数据区中。
  • Data Block是文件系统中用于存储数据的最小单位,通常具有固定的大小。
  • Data Blocks的大小和数量在文件系统格式化时设置,并且一旦设置,通常不能更改(除非重新格式化文件系统)。

竟然数据区的大小通常是固定的,那么它是如何存储不同大小的数据的呢?

存储机制

  1. 直接存储
    • 当文件大小小于或等于一个Data Block的大小时,文件内容将完整地存储在一个Data Block中。
    • 剩余的Data Block空间(如果有的话)将保持空闲,直到被其他文件内容占用。
  2. 间接存储
    • 当文件大小超过一个Data Block的容量时,文件内容会被分割成多个部分,并存储在多个Data Blocks中。
    • 每个Data Block存储文件内容的一部分,并通过某种方式(如inode中的指针)相互链接,以表示文件的完整内容。

3、文件系统

3.1、增删查改文件

将属性和数据分开存放的想法看起来很简单,但实际上是如何工作的呢?我们通过touch一个新文件来看看如何工作。

创建一个新文件主要有一下4个操作:
1. 存储属性

  • 内核先找到一个空闲的i节点(这里是263466)。内核把文件信息记录到其中。

2. 存储数据

  • 该文件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第一块数据复制到300,下一块复制到500,以此类推。

3. 记录分配情况

  • 文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。

4. 添加文件名到目录

  • 新的文件名abc。linux如何在当前的目录中记录这个文件?内核将入口(263466,abc)添加到目录文件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。

删除一个文件

  1. 查找 inode:通过文件名找到对应的 inode。
  2. 释放 inode 引用:减少 inode 的链接计数。
  3. 删除目录项:从父目录中删除指向该 inode 的条目。
  4. 回收资源:如果 inode 的链接计数降为 0,则回收 inode 和其关联的数据块。
  5. 更新文件系统元数据:更新文件系统的其他元数据,比如文件系统的块使用情况。

3.2、理解目录

目录也是文件,也有自己的 inode ,目录也要有自己的属性

目录有内容吗??要不要有数据块?里面放什么呢?

有内容,要有数据块,该目录下,文件的文件名 和 对应文件的 inode 的映射关系

为什么同一个目录下不能有同名文件?

ll 查看时,先找到目录的 inode, 目录内容中存储了文件的 inode,找到对应文件的 inode,就可以访问文件内容啦,例如说删除文件实际上是删除文件名与 inode 的关联,也就是从目录项中移除该文件名。这个操作需要对目录进行写操作,因为目录项(包含文件名)存储在磁盘上,并且需要被修改。但是我们限制了这一操作

目录下,没有 w ,我们无法删除文件,没有 r,我们无法查看文件是为什么?

因为想读取,目录不让读,拿什么查找到 inode,还有没有 x 无法 cd,都是通过对目录中 对文件 inode 的访问设置来管理的

目录是文件,也有 inode 编号,那么是如何管理的呢?

往上会一直访问到根目录,相当于是一个递归的实现

dentry 缓存:

  • 目录项对象:dentry代表文件系统中的一个目录项,即一个文件或目录的名称与其inode(索引节点)之间的关联。
  • 路径解析:当用户或程序请求访问一个文件或目录时,文件系统需要解析路径名,dentry缓存可以快速地定位到对应的inode,从而避免了每次都从磁盘读取目录信息

有绝对路径的话,不就可以从根目录往下拿到对应的 inode 了,为什么还要递归?

递归是我们从内部讲起的,就说要一路找上去,实际拿着文件路径从左到右解析就行,因为我们的任何一个文件,在进程内部都有路径,按照路径,应用层是知道文件和路径的。

相关推荐
项目題供诗3 分钟前
黑马python(二十五)
开发语言·python
only-lucky5 分钟前
C语言socket编程-补充
服务器·c语言·php
慌糖18 分钟前
RabbitMQ:消息队列的轻量级王者
开发语言·javascript·ecmascript
try2find20 分钟前
移动conda虚拟环境的安装目录
linux·运维·conda
码农101号43 分钟前
Linux中容器文件操作和数据卷使用以及目录挂载
linux·运维·服务器
醇醛酸醚酮酯43 分钟前
Qt项目锻炼——TODO清单(二)
开发语言·数据库·qt
jioulongzi1 小时前
记录一次莫名奇妙的跨域502(badgateway)错误
开发语言·python
PanZonghui1 小时前
Centos项目部署之Nginx 的安装与卸载
linux·nginx
PanZonghui1 小时前
Centos项目部署之安装数据库MySQL8
linux·后端·mysql
PanZonghui1 小时前
Centos项目部署之运行SpringBoot打包后的jar文件
linux·spring boot