Linux文件系统详解

博文大纲
* 磁盘组成与分区
* 文件系统特性
* Linux的EXT2文件系统
* 与目录树的关系
* Ext2/ext3文件的存取与日志式文件系统功能
* Linux文件系统的运行
* 挂载点的意义
* 其他Linux支持的文件系统与vfs
* XFS文件系统简介

整颗磁盘的组成:
圆形的盘片(主要记录数据的部分);
机械手臂,与在机械手臂上的磁头(可读写盘片上的数据);
主轴马达,可以转动盘片,让机械手臂的磁头在盘片上读写数据。

盘片上的物理组成:

(1)扇区(Sector)为最小的物理储存单位,且依据磁盘设计的不同,目前主要有 512Bytes 与 4K 两种格式;
将扇区组成一个圆,那就是柱面(Cylinder);
(2)早期的分区主要以柱面为最小分区单位,现在的分区通常使用扇区为最小分区单位(每个扇区都有其号码喔,就好像座位一样);
(3)磁盘分区表主要有两种格式,一种是限制较多的 MBR 分区表,一种是较新且限制较少的 GPT 分区表。
(4)MBR 分区表中,第一个扇区最重要,里面有:(1)主要开机区(Master boot record, MBR)及分区表(partition table),其中 MBR 占有 446 Bytes,而 partition table 则占有 64 Bytes。
(5)GPT 分区表除了分区数量扩充较多之外,支持的磁盘容量也可以超过 2TB。

实体磁盘及虚拟磁盘:

/dev/sd[a-p][1-128]:为实体磁盘的磁盘文件名

/dev/vd[a-d][1-128]:为虚拟磁盘的磁盘文件名

/dev/md[0-128]:软件磁盘阵列

/dev/Vgname/Lvname:逻辑卷

三个数据的意义:

superblock:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式与相关信息等;

inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;

block:实际记录文件的内容,若文件太大时,会占用多个

索引式文件系统:
1.(EXT4文件系统读取数据的过程)

系统先格式化出inode与block的区块。如下图,要访问一个文件时,首先找到这个文件的inode,根据inode中的权限查看当前用户是否有权力读取这个文件;然后根据inode中记录的block的号码,操作系统据此排列磁盘阅读顺序,一口气将四个block内容读出。最后找到block,读出数据。这种文件系统就叫做索引式文件系统

《Linux文件系统详解》

2.(U盘使用的文件系统(FAT))

U盘(闪存)一般使用FAT文件系统,而FAT文件系统并没有inode,每个block中记录着本文件下一个block的位置。所以FAT文件系统无法通过inode一次性将这个文件所有的block号码读取出来,而只能一个个地读取block后才能知道下一个block的位置。
如下图:
《Linux文件系统详解》

上图中我们假设文件的数据依序写入1->7->4->15号这四个 block 号码中, 但这个文件系统没有办法一口气就知道四个 block 的号码,他得要一个一个的将 block 读出后,才会知道下一个 block 在何处。如果同一个文件数据写入的 block 分散的太过厉害时,则我们的磁盘读取头将无法在磁盘转一圈就读到所有的数据, 因此磁盘就会多转好几圈能完整的读到到这个文件的内容。所以如果同一个文件的block分散地太开,那么读取一个文件的时间就会很长,所以就有所谓的“碎片整理“,就是将同一个文件的block们尽量放到一起去。但Linux的EXT4文件系统由于是索引式的,因此不太需要碎片整理。

Ext2 格式化后:

node的内容在记录档案的权限与相关属性,至于block区块则是在记录档案的实际内容。而且档案系统一开始就将inode与block规划好了,除非重新格式化(或者利用resize2fs等指令变更档案系统大小),否则inode与block固定后就不再变动。但是如果仔细考虑一下,如果我的档案系统高达数百GB时,那么将所有的inode与block通通放置在一起将是很不智的决定,因为inode与block的数量太庞大,不容易管理。
为此,因此Ext2 档案系统在格式化的时候基本上是区分为多个区块羣组(block group) 的,每个区块羣组都有独立的 inode/block/superblock 系统。感觉上就好像我们在当兵时,一个营里面有分成数个连,每个连有自己的联络系统, 但最终都向营部回报连上最正确的信息一般!这样分成一羣羣的比较好管理啦!整个来说,Ext2 格式化后有点像底下这样
《Linux文件系统详解》

区块羣组(block group)的六个主要内容:

  • data block (数据区块)
  • inode table (inode 表格)
  • Superblock (超级区块)
  • Filesystem Description (文件系统描述说明)
  • block bitmap (区块对照表)
  • inode bitmap (inode 对照表)

1、data block (数据区块)
《Linux文件系统详解》

基本限制如下:

(1)原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);
(2)每个block 内最多只能够放置一个档案的资料;
(3)承上,如果档案大于block 的大小,则一个档案会占用多个block 数量;
(4)承上,若档案小于block ,则该block 的剩余容量就不能够再被使用了(磁盘空间会浪费

2、inode table (inode 表格)

  • inode 记录的文件数据
  • 该文件的存取模式(read/write/excute);
  • 该文件的拥有者与羣组(owner/group);
  • 该文件的容量;
  • 该文件创建或状态改变的时间(ctime);
  • 最近一次的读取时间(atime);
  • 最近修改的时间(mtime);
  • 定义文件特性的旗标(flag),如 SetUID…;
  • 该文件真正内容的指向(pointer);

每个inode 大小均固定为128 bytes (新的ext4 与xfs 可设定到256 bytes);
每个档案都仅会占用一个inode 而已;

承上,因此档案系统能够建立的档案数量与inode 的数量有关;
系统读取档案时需要先找到inode,并分析inode 所记录的权限与使用者是否符合,若符合才能够开始实际读取 block 的内容

inode 的结构

《Linux文件系统详解》

12个直接指向: 12*1K=12K

由于是直接指向,所以总共可记录12笔记录,因此总额大小为如上所示;
间接: 256*1K=256K

每笔block号码的记录会花去4bytes,因此1K的大小能够记录256笔记录,因此一个间接可以记录的档案大小如上;
双间接: 2562561K=256 2 K

第一层block会指定256个第二层,每个第二层可以指定256个号码,因此总额大小如上;
三间接: 256256256*1K=256 3 K

第一层block会指定256个第二层,每个第二层可以指定256个第三层,每个第三层可以指定256个号码,因此总额大小如上;

总额:将直接、间接、双间接、三间接加总,得到12 + 256 + 256256 + 256256*256 (K) = 16GB

3、Superblock (超级区块)

记录的信息
block 与 inode 的总量;
未使用与已使用的 inode / block 数量;
block 与 inode 的大小(block 为 1, 2, 4K,inode 为 128Bytes 或 256Bytes);
filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘(fsck)的时间等文件系统的相关信息;
一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0 ,若未被挂载,则 valid bit 为 1

4、Filesystem Description (文件系统描述说明)

这个区段可以描述每个 block group 的开始与结束的 block 号码,以及说明每个区段(superblock, bitmap, inodemap,data block)分别介于哪一个 block 号码之间

5、block bitmap (区块对照表)

从 block bitmap 当中可以知道哪些 block 是空的,如果你删除某些文件时,那些文件原本占用的 block 号码就得要释放出来, 此时在 block bitmap 当中相对应到该 block 号码的标志就得要修改成为『未使用中』

6、inode bitmap (inode 对照表)

这个其实与 block bitmap 是类似的功能,只是 block bitmap 记录的是使用与未使用的 block 号码, 至于 inode bitmap 则是记录使用与未使用的 inode 号码

文件系统与目录树的关系:

目录:

《Linux文件系统详解》

目录树读取

由于目录树是由根目录开始读起,因此系统通过挂载的信息可以找到挂载点的inode号码(通常一个文件系统的最顶层inode号码会由2号开始),此时就能够得到根目录的inode里面的内容,并依据该inode读取根目录的block内的文件名数据,再一层一层地往下读到正确的文件名

与目录树的关系

filesystem 大小与磁盘读取性能:
关于文件系统的使用效率上,当你的一个文件系统规划的很大时,例如 100GB 这么大时,由于磁盘上面的数据总是来来去去的,所以,整个文件系统上面的文件通常无法连续写在一起(block 号码不会连续的意思),而是填入式的将数据填入没有被使用的 block 当中。如果文件写入的 block 真的分的很散,此时就会有所谓的文件数据离散的问题发生了

文件系统的行为:
一般来说,我们将 inode table 与 data block 称为数据存放区域,

至于其他例如 superblock、block bitmap 与 inodebitmap 等区段就被称为 metadata (中介数据)(因为superblock, inode bitmap 及 block bitmap 的数据是经常变动的,每次新增、移除、编辑时都可能会影响到这三个部分的数据,因此才被称为中介数据的啦)

日志式文件系统(Journaling filesystem)

  1. 预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;
  2. 实际写入:开始写入文件的权限与数据;开始更新 metadata 的数据;
  3. 结束:完成数据与 metadata 的更新后,在日志记录区块当中完成该文件的纪录。
  • (在这种机制下,断电后,由于新的数据还未成功写入,旧的数据就不会被擦除,保证了数据的完整性,使得整个文件结构不被破坏)


Linux 文件系统的运行:

Linux 系统上面文件系统与内存有非常大的关系:

系统会将常用的文件数据放置到内存的缓冲区,以加速文件系统的读/写;
承上,因此 Linux 的实体内存最后都会被用光!这是正常的情况!可加速系统性能;
你可以手动使用 sync 来强迫内存中设置为 Dirty 的文件回写到磁盘中;
若正常关机时,关机指令会主动调用 sync 来将内存的数据回写入磁盘内;
但若不正常关机(如跳电、死机或其他不明原因),由于数据尚未回写到磁盘内,因此重新开机后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)。

挂载点的意义(mount point)
挂载点一定是目录,该目录为进入该文件系统的入口

每个 filesystem 都有独立的 inode / block / superblock 等信息,这个文件系统要能够链接到目录树才能被我们使用。将文件系统与目录树结合的动作我们称为“挂载”

其他 Linux 支持的文件系统与 VFS:
VFS:(Linux的内核功能,用于读取文件系统)
常见的支持文件系统:

传统文件系统:ext2 / minix / MS-DOS / FAT (用 vfat 模块) / iso9660 (光盘)等等;
日志式文件系统: ext3 /ext4 / ReiserFS / Windows’ NTFS / IBM’s JFS / SGI’s XFS / ZFS
网络文件系统: NFS / SMBFS


其他 Linux 支持的文件系统与 VFS:

《Linux文件系统详解》


XFS 文件系统简介:

EXT 家族当前较伤脑筋的地方:支持度最广,但格式化超慢!家族当前较伤脑

Ext 文件系统家族对于文件格式化的处理方面,采用的是预先规划出所有的 inode/block/meta data 等数据,未来系统可以直接取用,不需要再进行动态配置的作法

xfs 文件系统在数据的分布上,主要规划为三个部份:

  • 数据区(data section)
  • 文件系统活动登录区(logsection)
  • 实时运行区(realtime section)

1、数据区(data section)

基本上,数据区就跟我们之前谈到的 ext 家族一样,包括 inode/data block/superblock 等数据,都放置在这个区块。这个数据区与 ext 家族的 block group 类似,也是分为多个储存区羣组(allocation groups)来分别放置文件系统所需要的数据。
每个储存区羣组都包含了(1)整个文件系统的 superblock、(2)剩余空间的管理机制、(3)inode的分配与追踪。
此外,inode与 block 都是系统需要用到时,这才动态配置产生,所以格式化动作超级快

2、文件系统活动登录区(log section)

在登录区这个区域主要被用来纪录文件系统的变化,其实有点像是日志区啦!文件的变化会在这里纪录下来,直到该变化完整的写入到数据区后,该笔纪录才会被终结。如果文件系统因为某些缘故(例如最常见的停电)而损毁时,系统会拿这个登录区块来进行检验,看看系统挂掉之前,文件系统正在运行些啥动作,藉以快速的修复文件系统。

3、实时运行区(realtime section)

当有文件要被创建时,xfs 会在这个区段里面找一个到数个的 extent 区块,将文件放置在这个区块内,等到分配完毕后,再写入到 data section 的 inode 与 block 去!这个 extent 区块的大小得要在格式化的时候就先指定,最小值是 4K 最大可到 1G。一般非磁盘阵列的磁盘默认为 64K 容量,而具有类似磁盘阵列的 stripe 情况下,则建议 extent 设置为与 stripe 一样大较佳。这个 extent 最好不要乱动,因为可能会影响到实体磁盘的性能喔。

XFS 文件系统的描述数据观察
《Linux文件系统详解》

  • 第 1 行里面的 isize 指的是 inode 的容量,每个有 256Bytes 这么大。至于 agcount 则是前面谈到的储存区羣组(allocationgroup)的个数,共有 4 个,agsize 则是指每个储存区羣组具有 65536 个 block 。配合第 4 行的 block 设置为 4K,因此整个文件系统的容量应该就是 4655364K 这么大!

  • 第 2 行里面 sectsz 指的是逻辑扇区(sector)的容量设置为 512Bytes 这么大的意思。

  • 第 4 行里面的 bsize 指的是 block 的容量,每个 block 为 4K 的意思,共有 262144 个 block 在这个文件系统内。

  • 第 5 行里面的 sunit 与 swidth 与磁盘阵列的 stripe 相关性较高。这部份我们下面格式化的时候会举一个例子来说明。

  • 第 7 行里面的 internal 指的是这个登录区的位置在文件系统内,而不是外部设备的意思。且占用了 4K * 2560 个 block,总共约10M 的容量。

  • 第 9 行里面的 realtime 区域,里面的 extent 容量为 4K。不过目前没有使用
点赞