引言从文件是否打开的角度我们可以将文件管理分为管理已经被打开的文件和管理没有被打开的文件(文件的存储)。本文将介绍在Linux中将如何管理没有被打开的文件即文件的存储问题。题目所说的文件系统用途就是管理未打开的文件。我们都知道一个文件被分为文件内容和文件属性这两部分。所以存储文件的时候就需要存储文件的内容和文件的属性。在Linux中文件的内容和属性是分开存储的文件的内容以块形式进行存储而文件的属性则以 inode 形式进行存储。对于这一点我们之后都会谈到。在这之前我们需要先了解硬盘。我们将要了解的硬盘并不是现在笔记本用的SSD而是十几年前用的机械硬盘。虽然现在笔记本并不用机械硬盘了但它仍有市场。而且在Linux出现的时候硬盘已经出现并且技术成熟。可以说Linux是诞生在硬盘之上的操作系统文件就存储在硬盘中。所以了解硬盘对我们了解文件系统是有所帮助的。注之后说到的硬盘指的都是机械硬盘。机械硬盘物理构成虽然硬盘可以存储数据但是它并不属于冯·诺依曼体系结构中的存储器它是计算机的外设。硬盘是一种机械设备我们可以看硬盘的内部照片图中的磁盘便是硬盘存储数据的地方磁头便是用来读写磁盘上的内容。在计算机读写数据的时候磁盘会高速旋转同时磁头会向内或者向外移动目的便是让磁头悬停在需要读写的数据所在的位置。磁头和磁盘距离很近但他们两者并不会相互接触对于这一点我们不必深究只要了解即可。那么磁盘怎么存储数据呢怎么向磁盘上写数据呢我们知道计算机只认识二进制它也只能处理二进制。计算机存储数据的时候是以二进制的形式进行存储的所以磁盘存储的就是二进制。想要存储二进制就需要两种状态表示 0 和 1。假设我有一个灯泡定义灯泡灭是0亮是1。那么我就可以通过灯泡的亮和灭表示一个二进制位。现在我有足够多的灯泡只需要令每个灯泡的亮和灭和需要存储的每一个二进制位对应起来并让这些灯泡一直保持这种状态不变这不就是将二进制数据存储下来了吗磁盘便是通过这种思路存储二进制数据的。读者有没有玩过吸铁石磁铁呢磁铁的两端具有不同的磁极即南极S极和北极N极。我们可以通过一些手段将磁铁的南北极位置进行调换。调换之后和调换之前的状态可以用来表示0和1至于哪种状态表示0哪种状态表示1这是需要人为规定的。磁盘也是通过磁极的不同存储二进制位的。磁盘表面存在许多的磁性粒子这些磁性粒子表现出来的磁极方向就代表二进制位许多磁性粒子的组合便能够表示二进制数据之后只要这些磁性粒子的状态不改变那么磁盘便能够存储二进制数据。知道磁盘是怎么存储数据后写数据也就很简单了实现肯定不简单。只要改变磁盘上磁性粒子的状态那么就能往磁盘上写数据了。这个过程便是由磁头完成。对于磁盘的存储和修改到此就结束了如果对此感兴趣请自行查阅相关资料。存储构成知道了硬盘的物理构成后接下来我们便来了解一下硬盘的存储构成。首先我们需要知道一些名词扇面、磁道、扇区和柱面。从硬盘的内部照片中可以看出一个硬盘中有许多磁盘而一个磁盘有上下两面这两面都可以用来存储数据。我们将磁盘的一面叫做扇面。那么什么是磁道呢我们可以看下面一张图在磁盘上通过多个同心圆我们可以将磁盘的扇面分为多个圆环这些圆环就被称作磁道。而扇区便是在磁道的基础上继续划分如图过磁盘圆心做多条长度和磁盘环宽相等的线段将磁道分为多个部分其中这一个部分就被称作扇区。相同磁道上的扇区面积是相同的。而磁盘上各个扇区的存储大小是相同的一般而言是512B 或者 4KB。至于柱面它也和磁道有关系。一个硬盘会有多张磁盘即多个扇面。为了能够对这些扇面上的数据进行读写就存在多个磁头。这些磁头都连接在同一个马达上所以这些磁头是同时移动的。这也就造成了磁头到达一个扇面的某个磁道时其他磁头也到达各自的磁道从上往下看这些磁道便组成一个面。如图我们在磁盘上存储数据并不是在磁盘上随便找个空位置开始存储而是根据这样的划分在磁盘的某个盘面的某个磁道上的某个扇区开始存储数据。可以这么说磁盘被访问的基本单元就是扇区。这时我们可以将磁盘看做是由无数个扇区组成的存储介质。那么向磁盘真正写数据前需要定位一个扇区(确认地址)即确定扇面(磁头)寻找磁道(柱面)确定扇区这便是CHS寻址方式。所以上面所说的磁头的移动目的是确定柱面。盘片的旋转便是为了定位扇区。硬盘效率CHS寻址方式是依靠磁盘旋转和磁头移动的简单地说运动越少效率越高。所以在软件设计上设计者要有意识地将相关数据放在一起例如同一柱面上。对磁盘的逻辑抽象在磁盘上我们采用的是CHS寻址方式但在Linux系统中管理磁盘空间时采用的是LBA寻址方式。在讲LBA寻址方式之前我们先讲一个题外话。不知读者有没有见过或者用过磁带。我们在使用磁带时磁带会进行旋转。在旋转的同时机器会读出存在磁带上的数据。正常情况下我们看磁带是一个圆但如果我们将其延展开它就是一条线。如下图也就是说虽然磁带是圆形的但逻辑上它是一个线性的。磁盘也是同样的道理我们在逻辑上可以将磁盘看成是线性的。磁盘的每个扇面有多个磁道每个磁道有多个扇区那么整个磁盘就相当于一个基于扇区的数组。在这个基础上任意的扇区就有下标我们根据下标就能确认该下标对应的扇面磁道以及磁道中的扇区。即逻辑扇区地址可以转化成为物理扇区地址这种寻址方式便是LBA寻址方式。文件系统(ext2文件系统)在说文件系统的时候我们需要搞懂一个问题我们有一定容量的磁盘空间哪些存文件属性呢哪些存文件内容呢在回答这个问题之前我们需要一些知识。首先当磁盘空间很大很难管理时怎么办ext2文件系统采用分治的思想。第一步便是对磁盘空间进行分区实际上我们每个人刚买电脑时就做过这事。那怎么分区呢确定区域开始和结束的扇区下标。在分区之后我们只要将一个区域管理好那么管理其他的区域时只要复制粘贴即可因为每个分区本质上是相同的即以扇区为单位的一个有限数组。那么怎么管理一个分区呢Linux将分区又分为几个部分进行管理。具体如图一个分区首先会分成1个 boot block 区和多个 block group 区。Boot Blockboot block 区位于分区开始位置并且它的大小固定。这个区域一般存储着引导加载程序。在系统启动时如果该分区被设置为启动分区那么 BIOS/UEFI 会读取该区域的代码来加载操作系统。如果该分区不是启动分区那么该区域一般为空或者未使用但它仍会存在以保持兼容性和一致性。Block group当一个分区存在多个 group 时我们只需要管理好一个 group便能管理好所有 group从而管理好一个分区进而管理好整个磁盘空间。那么怎么管理一个 group呢继续分成几部分进行管理。Data blocks这个区域被用来存放文件内容以块的形式呈现。常见的块大小为 4KB这是文件系统的块大小当然也存在 1KB、2KB等。我们可以通过相关指令更改文件系统的块大小具体的需要读者自行搜索。虽然整个磁盘是以扇区为单位进行管理但是文件系统对这个区域进行操作时是以块为单位进行操作的。例如如果我需要 1KB 的空间来存储文件文件系统会给我一个块的空间存储这个文件。而且通常即使一个块未被写满该块也不能存储其他文件的数据。很明显这种以块为单位的分配是可能造成空间浪费的但是一个文件也不一定只占用一个块所以空间的浪费并不严重。inode Table顾名思义这个区域用来存放文件的inode。至于为什么被称作表具体原因这里不详谈读者请自行搜索资料。那什么是 inode 呢之前说道inode存储的是文件的属性但这只是inode的作用。实际上inode 是 ext2 文件系统的核心数据结构他并不是一种文件。类似于在C语言中创建一个结构体该结构体名字是 inode里面存储的是文件的所有属性。一般一个 inode 的大小是 128B并且一个文件对应一个 inode。同时在 Linux 中文件属性并不包含文件名。那么在 Linux 中怎么区分文件呢通过 inode 编号。每个 inode 都有一个唯一的编号又因为一个文件对应一个 inode所以可以通过 inode 标识一个文件。指令 ls -i 可以显示文件的 inode 编号。既然我们可以通过 inode 编号标识文件那么如果只知道 inode 编号怎么知道文件内容存储在哪里呢inode 中除了有文件属性外它还有一个定长的 blocks 数组通常包含15个元素这个数组中存放的是文件内容所在的块编号Data Blocks 区域不仅以块的形式呈现每个块都拥有自己的编号。通过这个数组中存储的编号我们可以找到文件内容。那在 ext2 中一个文件最大只能占据 15 个块吗并不是。在 blocks 数组中前 12 个元素存储的是直接索引第 13、14、15 个元素分别是一级、二级、三级间接索引。也就是说前 12 个元素直接指向文件内容所在的块第 13 个元素指向的块存放的是直接索引第14个元素指向的块存放的是一级索引以此类推。如果每个块大小为 4KB每个直接索引占 4B那么一个文件最大为Block bitmap按照命名我们就能知道这个区域的作用类似于位图。它映射一个块组中每个块对应的块号标记一个块是否被使用从而能够快速寻找未使用的块。一个比特位值为1代表对应的数据块被使用为0代表空闲问题1Data Blocks中的块号分配规则是什么能够跨group吗能够跨区吗问题2怎么映射的inode bitmap这个区域的作用和 Block bitmap 类似不过它映射的是 inode 的编号。问题1inode 的编号分配规则又是什么是仅在一个 group 中 inode 编号唯一还是整个系统中唯一问题2怎么映射的问题3删除和创建文件的具体过程是什么样的问题4删除文件时是否需要清空文件Group Descriptor Table(GDT)简述GDT组描述符表它的作用是描述整个 group 的基本信息和使用情况以便快速定位和管理 group 内的资源。比如 GDT 会记录 group 中块位图和 inode 位图的磁盘块号同时记录 inode Table 的起始磁盘块号。它也会记录 group 中的空闲块和空闲 inode 的数量。总之可以通过 GDT 更好地管理一个组。Super BlockSuper Block超级块它描述整个分区的文件系统的信息。它包含整个分区的基本使用情况一共有多少组每个组的大小每个组的 inode 数量每个组的 block 数量每个组的 inode起始编号文件系统的类型和名称等等这些东西都交由超级块描述。可以认为它是一个分区的管理块。正因为超级块是隶属于整个分区的所以没有必要在每个 group 中都存在超级块否则写磁盘时需要对所有超级块进行更新浪费时间。不过通常来讲超级块不止存在一份系统可能会在部分 group 中复制超级块防止超级块出问题时导致文件系统挂掉。既然在有些组中存在超级块有些组中没有超级块我们在访问时怎么判断访问的这块是不是超级块呢超级块中存在“魔数”字段它是超级块的唯一标识符。“魔数”存储在超级块中的固定位置并且它的值也是固定的(具体的读者自行查阅)。我们可以借助“魔数”判断一个块是不是超级块。什么是文件系统参考AI我们现在知道Linux管理磁盘是先分区管理每个区对于每个区分组进行管理。简单地说一个分区的管理方式就是我们常说的文件系统。形象地说我们现在有一大块空白的土地原始磁盘空间我们想在空地上建一个图书馆来管理书籍在磁盘上存储并管理数据。我们首先在空地上划出一块区域专门建立图书馆磁盘分区其他区域可以建其他东西也能用来存储数据。图书馆建好后我们需要一套管理规则对图书馆进行管理管理磁盘分区这套管理规则就相当于文件系统。而 ext2 文件系统就相当于一套具体的管理规则。正式地说文件系统File System是一套用于明确、高效地组织、存储、管理、检索、命名和保护磁盘上数据的软件方法、数据结构和规则。文件系统是一种框架或者模式而 ext2文件系统便是一种具体实现。现在我们应该已经对 ext2 文件系统有了一定的了解了所以可以试着解决一些问题了。
Linux文件系统I
引言从文件是否打开的角度我们可以将文件管理分为管理已经被打开的文件和管理没有被打开的文件(文件的存储)。本文将介绍在Linux中将如何管理没有被打开的文件即文件的存储问题。题目所说的文件系统用途就是管理未打开的文件。我们都知道一个文件被分为文件内容和文件属性这两部分。所以存储文件的时候就需要存储文件的内容和文件的属性。在Linux中文件的内容和属性是分开存储的文件的内容以块形式进行存储而文件的属性则以 inode 形式进行存储。对于这一点我们之后都会谈到。在这之前我们需要先了解硬盘。我们将要了解的硬盘并不是现在笔记本用的SSD而是十几年前用的机械硬盘。虽然现在笔记本并不用机械硬盘了但它仍有市场。而且在Linux出现的时候硬盘已经出现并且技术成熟。可以说Linux是诞生在硬盘之上的操作系统文件就存储在硬盘中。所以了解硬盘对我们了解文件系统是有所帮助的。注之后说到的硬盘指的都是机械硬盘。机械硬盘物理构成虽然硬盘可以存储数据但是它并不属于冯·诺依曼体系结构中的存储器它是计算机的外设。硬盘是一种机械设备我们可以看硬盘的内部照片图中的磁盘便是硬盘存储数据的地方磁头便是用来读写磁盘上的内容。在计算机读写数据的时候磁盘会高速旋转同时磁头会向内或者向外移动目的便是让磁头悬停在需要读写的数据所在的位置。磁头和磁盘距离很近但他们两者并不会相互接触对于这一点我们不必深究只要了解即可。那么磁盘怎么存储数据呢怎么向磁盘上写数据呢我们知道计算机只认识二进制它也只能处理二进制。计算机存储数据的时候是以二进制的形式进行存储的所以磁盘存储的就是二进制。想要存储二进制就需要两种状态表示 0 和 1。假设我有一个灯泡定义灯泡灭是0亮是1。那么我就可以通过灯泡的亮和灭表示一个二进制位。现在我有足够多的灯泡只需要令每个灯泡的亮和灭和需要存储的每一个二进制位对应起来并让这些灯泡一直保持这种状态不变这不就是将二进制数据存储下来了吗磁盘便是通过这种思路存储二进制数据的。读者有没有玩过吸铁石磁铁呢磁铁的两端具有不同的磁极即南极S极和北极N极。我们可以通过一些手段将磁铁的南北极位置进行调换。调换之后和调换之前的状态可以用来表示0和1至于哪种状态表示0哪种状态表示1这是需要人为规定的。磁盘也是通过磁极的不同存储二进制位的。磁盘表面存在许多的磁性粒子这些磁性粒子表现出来的磁极方向就代表二进制位许多磁性粒子的组合便能够表示二进制数据之后只要这些磁性粒子的状态不改变那么磁盘便能够存储二进制数据。知道磁盘是怎么存储数据后写数据也就很简单了实现肯定不简单。只要改变磁盘上磁性粒子的状态那么就能往磁盘上写数据了。这个过程便是由磁头完成。对于磁盘的存储和修改到此就结束了如果对此感兴趣请自行查阅相关资料。存储构成知道了硬盘的物理构成后接下来我们便来了解一下硬盘的存储构成。首先我们需要知道一些名词扇面、磁道、扇区和柱面。从硬盘的内部照片中可以看出一个硬盘中有许多磁盘而一个磁盘有上下两面这两面都可以用来存储数据。我们将磁盘的一面叫做扇面。那么什么是磁道呢我们可以看下面一张图在磁盘上通过多个同心圆我们可以将磁盘的扇面分为多个圆环这些圆环就被称作磁道。而扇区便是在磁道的基础上继续划分如图过磁盘圆心做多条长度和磁盘环宽相等的线段将磁道分为多个部分其中这一个部分就被称作扇区。相同磁道上的扇区面积是相同的。而磁盘上各个扇区的存储大小是相同的一般而言是512B 或者 4KB。至于柱面它也和磁道有关系。一个硬盘会有多张磁盘即多个扇面。为了能够对这些扇面上的数据进行读写就存在多个磁头。这些磁头都连接在同一个马达上所以这些磁头是同时移动的。这也就造成了磁头到达一个扇面的某个磁道时其他磁头也到达各自的磁道从上往下看这些磁道便组成一个面。如图我们在磁盘上存储数据并不是在磁盘上随便找个空位置开始存储而是根据这样的划分在磁盘的某个盘面的某个磁道上的某个扇区开始存储数据。可以这么说磁盘被访问的基本单元就是扇区。这时我们可以将磁盘看做是由无数个扇区组成的存储介质。那么向磁盘真正写数据前需要定位一个扇区(确认地址)即确定扇面(磁头)寻找磁道(柱面)确定扇区这便是CHS寻址方式。所以上面所说的磁头的移动目的是确定柱面。盘片的旋转便是为了定位扇区。硬盘效率CHS寻址方式是依靠磁盘旋转和磁头移动的简单地说运动越少效率越高。所以在软件设计上设计者要有意识地将相关数据放在一起例如同一柱面上。对磁盘的逻辑抽象在磁盘上我们采用的是CHS寻址方式但在Linux系统中管理磁盘空间时采用的是LBA寻址方式。在讲LBA寻址方式之前我们先讲一个题外话。不知读者有没有见过或者用过磁带。我们在使用磁带时磁带会进行旋转。在旋转的同时机器会读出存在磁带上的数据。正常情况下我们看磁带是一个圆但如果我们将其延展开它就是一条线。如下图也就是说虽然磁带是圆形的但逻辑上它是一个线性的。磁盘也是同样的道理我们在逻辑上可以将磁盘看成是线性的。磁盘的每个扇面有多个磁道每个磁道有多个扇区那么整个磁盘就相当于一个基于扇区的数组。在这个基础上任意的扇区就有下标我们根据下标就能确认该下标对应的扇面磁道以及磁道中的扇区。即逻辑扇区地址可以转化成为物理扇区地址这种寻址方式便是LBA寻址方式。文件系统(ext2文件系统)在说文件系统的时候我们需要搞懂一个问题我们有一定容量的磁盘空间哪些存文件属性呢哪些存文件内容呢在回答这个问题之前我们需要一些知识。首先当磁盘空间很大很难管理时怎么办ext2文件系统采用分治的思想。第一步便是对磁盘空间进行分区实际上我们每个人刚买电脑时就做过这事。那怎么分区呢确定区域开始和结束的扇区下标。在分区之后我们只要将一个区域管理好那么管理其他的区域时只要复制粘贴即可因为每个分区本质上是相同的即以扇区为单位的一个有限数组。那么怎么管理一个分区呢Linux将分区又分为几个部分进行管理。具体如图一个分区首先会分成1个 boot block 区和多个 block group 区。Boot Blockboot block 区位于分区开始位置并且它的大小固定。这个区域一般存储着引导加载程序。在系统启动时如果该分区被设置为启动分区那么 BIOS/UEFI 会读取该区域的代码来加载操作系统。如果该分区不是启动分区那么该区域一般为空或者未使用但它仍会存在以保持兼容性和一致性。Block group当一个分区存在多个 group 时我们只需要管理好一个 group便能管理好所有 group从而管理好一个分区进而管理好整个磁盘空间。那么怎么管理一个 group呢继续分成几部分进行管理。Data blocks这个区域被用来存放文件内容以块的形式呈现。常见的块大小为 4KB这是文件系统的块大小当然也存在 1KB、2KB等。我们可以通过相关指令更改文件系统的块大小具体的需要读者自行搜索。虽然整个磁盘是以扇区为单位进行管理但是文件系统对这个区域进行操作时是以块为单位进行操作的。例如如果我需要 1KB 的空间来存储文件文件系统会给我一个块的空间存储这个文件。而且通常即使一个块未被写满该块也不能存储其他文件的数据。很明显这种以块为单位的分配是可能造成空间浪费的但是一个文件也不一定只占用一个块所以空间的浪费并不严重。inode Table顾名思义这个区域用来存放文件的inode。至于为什么被称作表具体原因这里不详谈读者请自行搜索资料。那什么是 inode 呢之前说道inode存储的是文件的属性但这只是inode的作用。实际上inode 是 ext2 文件系统的核心数据结构他并不是一种文件。类似于在C语言中创建一个结构体该结构体名字是 inode里面存储的是文件的所有属性。一般一个 inode 的大小是 128B并且一个文件对应一个 inode。同时在 Linux 中文件属性并不包含文件名。那么在 Linux 中怎么区分文件呢通过 inode 编号。每个 inode 都有一个唯一的编号又因为一个文件对应一个 inode所以可以通过 inode 标识一个文件。指令 ls -i 可以显示文件的 inode 编号。既然我们可以通过 inode 编号标识文件那么如果只知道 inode 编号怎么知道文件内容存储在哪里呢inode 中除了有文件属性外它还有一个定长的 blocks 数组通常包含15个元素这个数组中存放的是文件内容所在的块编号Data Blocks 区域不仅以块的形式呈现每个块都拥有自己的编号。通过这个数组中存储的编号我们可以找到文件内容。那在 ext2 中一个文件最大只能占据 15 个块吗并不是。在 blocks 数组中前 12 个元素存储的是直接索引第 13、14、15 个元素分别是一级、二级、三级间接索引。也就是说前 12 个元素直接指向文件内容所在的块第 13 个元素指向的块存放的是直接索引第14个元素指向的块存放的是一级索引以此类推。如果每个块大小为 4KB每个直接索引占 4B那么一个文件最大为Block bitmap按照命名我们就能知道这个区域的作用类似于位图。它映射一个块组中每个块对应的块号标记一个块是否被使用从而能够快速寻找未使用的块。一个比特位值为1代表对应的数据块被使用为0代表空闲问题1Data Blocks中的块号分配规则是什么能够跨group吗能够跨区吗问题2怎么映射的inode bitmap这个区域的作用和 Block bitmap 类似不过它映射的是 inode 的编号。问题1inode 的编号分配规则又是什么是仅在一个 group 中 inode 编号唯一还是整个系统中唯一问题2怎么映射的问题3删除和创建文件的具体过程是什么样的问题4删除文件时是否需要清空文件Group Descriptor Table(GDT)简述GDT组描述符表它的作用是描述整个 group 的基本信息和使用情况以便快速定位和管理 group 内的资源。比如 GDT 会记录 group 中块位图和 inode 位图的磁盘块号同时记录 inode Table 的起始磁盘块号。它也会记录 group 中的空闲块和空闲 inode 的数量。总之可以通过 GDT 更好地管理一个组。Super BlockSuper Block超级块它描述整个分区的文件系统的信息。它包含整个分区的基本使用情况一共有多少组每个组的大小每个组的 inode 数量每个组的 block 数量每个组的 inode起始编号文件系统的类型和名称等等这些东西都交由超级块描述。可以认为它是一个分区的管理块。正因为超级块是隶属于整个分区的所以没有必要在每个 group 中都存在超级块否则写磁盘时需要对所有超级块进行更新浪费时间。不过通常来讲超级块不止存在一份系统可能会在部分 group 中复制超级块防止超级块出问题时导致文件系统挂掉。既然在有些组中存在超级块有些组中没有超级块我们在访问时怎么判断访问的这块是不是超级块呢超级块中存在“魔数”字段它是超级块的唯一标识符。“魔数”存储在超级块中的固定位置并且它的值也是固定的(具体的读者自行查阅)。我们可以借助“魔数”判断一个块是不是超级块。什么是文件系统参考AI我们现在知道Linux管理磁盘是先分区管理每个区对于每个区分组进行管理。简单地说一个分区的管理方式就是我们常说的文件系统。形象地说我们现在有一大块空白的土地原始磁盘空间我们想在空地上建一个图书馆来管理书籍在磁盘上存储并管理数据。我们首先在空地上划出一块区域专门建立图书馆磁盘分区其他区域可以建其他东西也能用来存储数据。图书馆建好后我们需要一套管理规则对图书馆进行管理管理磁盘分区这套管理规则就相当于文件系统。而 ext2 文件系统就相当于一套具体的管理规则。正式地说文件系统File System是一套用于明确、高效地组织、存储、管理、检索、命名和保护磁盘上数据的软件方法、数据结构和规则。文件系统是一种框架或者模式而 ext2文件系统便是一种具体实现。现在我们应该已经对 ext2 文件系统有了一定的了解了所以可以试着解决一些问题了。