文章目录
一、初始文件系统
二、理解磁盘文件
三、了解磁盘
四、深入理解磁盘文件
4、1 磁盘分区
4、2 分区存储细节
4、3 磁盘文件的操作
4、3、1 查找某个磁盘文件
4、3、2 创建文件
4、3、3 对文件进行写入
4、3、4 删除文件
4、4 再次理解文件权限
🙋♂️ 作者:@Ggggggtm 🙋♂️
👀 专栏:Linux从入门到精通 👀
💥 标题:文件系统💥
❣️ 寄语:与其忙着诉苦,不如低头赶路,奋路前行,终将遇到一番好风景 ❣️
一、初始文件系统
文件可以被分为两种:内存文件(打开的文件)、磁盘文件(未被打开的文件)。在Linux操作系统中,内存文件和磁盘文件是两种不同的概念,它们在系统中的作用和存储方式都有所不同。下面将对这两种文件类型进行详细的解释和举例。
内存文件(Memory Files):
- 内存文件是指在计算机的内存中创建的文件,它们通常用于临时存储数据,不会被永久保存在硬盘上。
- 内存文件的存在是为了提高数据访问速度,因为内存的读写速度远快于磁盘。
- 内存文件通常用于缓存、临时数据存储、进程间通信等用途。
举例:
- 临时文件:临时文件可以在内存中创建,以便快速访问和操作。例如,当您在文本编辑器中编辑文档时,编辑器可能会将内容保存到内存中的临时文件,以便快速响应您的操作。
- 共享内存:共享内存是一种进程间通信方式,多个进程可以通过共享内存访问相同的数据。这些共享数据通常存储在内存中的文件中。
磁盘文件(Disk Files):
- 磁盘文件是指存储在计算机硬盘上的文件,它们通常用于永久存储数据,即使计算机重新启动也不会丢失。
- 磁盘文件可以包括文本文件、二进制文件、配置文件、多媒体文件等各种类型。
举例:
- 文本文件:文本文件包括纯文本文件(如.txt文件)和代码文件(如.c、.py文件)。这些文件通常包含文本内容,可以用文本编辑器打开和编辑。
- 图像文件:图像文件可以是磁盘上存储的图像,如.jpg、.png、.gif等格式的文件。这些文件通常用于存储图像或照片。
- 数据库文件:数据库文件通常存储在硬盘上,包括各种数据库系统的数据文件,如SQLite、MySQL、PostgreSQL等。
- 日志文件:日志文件用于记录系统和应用程序的运行信息,通常存储在硬盘上,如/var/log目录中的日志文件。
通俗的理解内存文件:我们通常对文件进行读写时,都是需要先将文件打开,也就是加载到系统的内存中。同时对打开的文件创建对应的数据结构。本篇文章重点讲解磁盘文件,内存文件详解可参考文章(文件描述符详解)。
二、理解磁盘文件
我们知道,打开的文件都是加载到了内存当中,那么没有打开的文件呢?系统中肯定也会存在大量没有被打开的文件,这些文件都是被保存在了磁盘当中。这也是我们称之为磁盘文件的原因。我们应该怎么理解磁盘文件呢?这里给出两个角度:
- 单个文件的角度:这些文件在哪里呢?文件有多大呢?文件的属性和内容是怎么存储的呢等等。
- 系统文件的角度:一共有多少个文件?文件的属性在哪里?如何快速找到文件?还可以存储多少个文件等等。
带着这些问题,我们接着往下探寻。
三、了解磁盘
在学习磁盘文件之前,我们可以先了解一下磁盘的结构。我们先看如下图:
磁盘的硬件结构主要包括以下几个关键部分:
盘片(Platters): 磁盘通常由多个盘片叠放在一起构成。每个盘片都是薄而圆的,由磁性材料制成,用于存储数据。
磁头(Read/Write Heads): 磁头是位于磁盘上方和下方的装置,用于读取和写入数据。它们悬浮在盘片上,可以移动到不同的径向位置。
磁道(Tracks): 磁盘表面被划分为多个同心圆磁道,每个磁道可以存储数据。
扇区(Sectors): 每个磁道又被划分为多个扇区,通常以512字节或4K字节为单位,用于存储数据。
每个盘片都有自己的磁道与扇区。磁道与扇区的理解可参照下图:
数据是怎么向磁盘中写入的呢?磁盘的存储数据方式主要有两种:
- 扇区存储:将磁盘划分为多个扇区,每个扇区包含512字节的数据。每个扇区都有一个唯一的地址,可以通过地址来访问扇区中的数据。
- 磁道存储:将磁盘划分为多个磁道,每个磁道包含多个扇区。磁道是按照同心圆的方式排列的,每个磁道都有一个唯一的地址,可以通过地址来访问磁道中的扇区。
具体存储也可分为如下几个步骤:
- 首先确定读写信息在磁盘的哪个盘面。
- 然后再去查找所在在磁盘的哪个柱面(多个盘片上的相同半径大小的磁道形成柱面)。
- 找到柱面后,最后确定所在的磁道和扇区里即可。
举例来说,如果需要读取一个文件的数据,计算机会使用磁盘的寻址方式来找到文件所在的磁道号和扇区号,然后磁头会定位到该位置,读取相应的数据。说起来简单,磁盘空间这么大,怎么就那么容易的就找到了呢?下面我们再来深入的去理解,看看到底是怎么做到的。
四、深入理解磁盘文件
4、1 磁盘分区
通过上述对磁盘的了解,我们直达了磁盘是由多个盘片组成的。怎么可以很好的存储和寻址呢?
正如上图所示,我们可以把圆形的磁盘抽象成一个连续的线性结构,也就是所谓的数组。这样存储和寻址就方便了(对应到底层就是大量的除操作和除余操作)。具体如下图:
但是既是可以抽象为线性结构,由于整个磁盘的空间太大,整体管理起来还是太过复杂。为了方便管理,于是就对磁盘空间进行了区域划分。如下图:
磁盘的分区也就是我们对应的分盘。分盘时还经常伴随着格式化的操作。格式化也就是对磁盘中的分区进行初始化的一种操作,这种操作通常会导致现有的磁盘或分区中所有的文件被清除。同时写入一个管理信息。
而不同的文件系统写入的管理信息是有所不同的。Linux下常见的文件系统类型:
- ext2/3/4:这是Linux中最常用的文件系统类型,用于存储Linux系统的大部分文件。它支持大文件和文件系统扩展,但不支持文件系统校验。
- XFS:这是一种高性能的文件系统,用于存储大型文件和数据库。它支持大文件、文件系统校验和文件系统扩展。
- Btrfs:这是一种新型的文件系统,用于存储大型文件和数据库。它支持大文件、文件系统校验、文件系统扩展和数据复制。
- ReiserFS:这是一种快速的文件系统,用于存储大型文件和数据库。它支持大文件、文件系统校验和文件系统扩展。
- JFS:这是一种高性能的文件系统,用于存储大型文件和数据库。它支持大文件、文件系统校验和文件系统扩展。
- NTFS:这是一种Windows操作系统使用的文件系统,可以在Linux系统中使用。它支持大文件、文件系统校验和文件系统扩展。
最为常见的还是ext2/3/4。所以我们就以ext2进行展开详解。
4、2 分区存储细节
对整个磁盘进行分区后,现在我们只需要对每个分区管理好就可以了。为了对分区进行边界管理,于是又将一个分区內部划分为了多个块组。如下图:
现在我们只需要做的就是,将每个块组进行管理,其他的按照同样的方式进行管理就可以将整个磁盘很好的组织管理了!对于每一个分区来说,分区的头部会包括一个启动块(Boot Block),对于该分区的其余区域,EXT2文件系统会根据分区的大小将其划分为一个个的块组(Block Group)。启动块包含了磁盘分区表,用于指示磁盘上有哪些分区,每个分区的大小、类型等信息。启动快的大小是固定的,且每个分区中都有一个,且存储的内存都是相同的,也就是为了数据丢失后的快速恢复。
然后每个组块都有着相同的组成结构,都是由超级块(Super Block)、块组描述符表(Group Descriptor Table)、块位图(Block Bitmap)、inode位图(inode Bitmap)、inode表(inode Table)以及数据表(Data Block)组成。具体如下图:
他们各自的作用如下:
- Super Block: 存放文件系统本身的结构信息。记录的信息主要有:Data Block和inode的总量、未使用的Data Block和inode的数量、一个Data Block和inode的大小、最近一次挂载的时间、最近一次写入数据的时间、最近一次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可以说整个文件系统结构就被破坏了。
- Group Descriptor Table: 块组描述符表,描述该分区当中块组的属性信息。
- Block Bitmap: 块位图当中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用。
- inode Bitmap: inode位图当中记录着每个inode是否空闲可用。
- inode Table: 存放文件属性,即每个文件的inode。inode是一个大小为128字节的空间,保存的是对应文件的属性。该块组内,所有文件的inode空间的集合,需要标识唯一性,每一个inode块,都要有一个inode编号!一般而言一个文件,一个inode,一个inode编号。
- Data Blocks: 存放文件内容。
通过上述的管理方式,就可以很好的将磁盘的内容和属性分来进行存储。
4、3 磁盘文件的操作
inode本质上就是一个结构体,里面存储了文件的大部分属性信息。其中每个indoe都有自己的inode编号,但是inode中并不存储文件名。因此,磁盘并不认识文件名,只认识inode编号。那么我们是怎么通过文件名字找到对应的inode编号了呢?
4、3、1 查找某个磁盘文件
当我们在某个目录下创建一个文件时,也会创建名字。不要忘记了,目录(文件夹)是不是一个文件呢?目录也是一个问价,当我们在目录下创建文件时,在目录所对应的data block中存储文件名与inode的映射信息。在Linux下,我们也可通过 ll -i 查看其inode编号。如下图:
现在就是:我们知道了某个路径下的文件名字,就可以在该目录下找到对应的inode编号,在到对应的块组中找到对应的inode和其内容。当我们创建文件时,该文件就会有一个对应的inode和data block来存储器属性和信息。
4、3、2 创建文件
注意,在对磁盘进行分盘时就会对磁盘进行格式化。格式化就是将对应的每个block group组中的信息进行初始化。例如:将inode bitmap和block bitmap全部初始化为0等等写入操作。
此时,我们再创建文件,也就是在对应的block group中的inode bitmap找到一个没有使用的inode和在对应的block bitmap中找到对应没被使用的block进行存储属性和内容。同时,将该文件的文件名和inode的映射关系添加到目录文件的数据块中。
4、3、3 对文件进行写入
当我们理解创建文件后,那么对文件的写入也就简单了。首先,在对应的目录中找到对应的inode编号。通过inode编号找到对应的分区和块组。然后找到对应的inode和其data block,对文件的写入,无非就是内容的增删查改和对文件属性的修改。
4、3、4 删除文件
有时候我们发现,当下载一个app时会需要很长时间,删除时反而会很快。这是为很么呢?在下载时,我们就是在文件对应的data block中一点一点写入数据。删除时,我们只需要找到对应的inode bitmap 和 block bitmap后,将其所对应的比特位进行置0(表示该比特位的inode和block未被使用)。真正的数据其实并没有被删除,只不过下此再使用时该空间时会将数据进行覆盖。所以被删除的数据是能够恢复的!前提是对应的inode没有被分配出去和原本对应的空间块没有被覆盖。
4、4 再次理解文件权限
当我们能够在目录下创建文件时,需要该目录有 w 权限,也就是写权限。为什么呢?现在我们可以很好的理解了,因为我们在目录下创建文件时需要把inode编号和文件名写入目录文件所对应的data block中!
当我们想访问某个目录下所有文件及其文件的属性时,需要r权限,也就是读权限。原因就在于我们需要在目录中找到文件名对应的inode编号,然后再去对应的inode中找到属性进行输出。
为什么进入目录是需要可执行权限呢?这是因为Linux系统目录也被视为一种特殊类型的文件,称为目录文件。这些目录文件包含了文件和子目录的列表以及它们的元数据信息。需要执行权限来改变当前工作目录。当用户尝试进入目录时,系统实际上是在运行一个命令(例如cd),该命令需要执行权限才能运行。