1. Linux系统上常见文件系统格式介绍

       文件系统是操作系统最为重要的一部分,它定义了磁盘上储存文件的方法和数据结构。每种操作系统都有它独有的文件系统类型。如Windows所用的文件系统主要有FAT16、FAT32和NTFS,Linux所用的文件系统主要有ext2、ext3、Ext4和ReiserFS等。
       一块磁盘,要先分区,然后再格式化,否则不能使用,而这个格式化的过程,就是文件系统创建的过程,也可以这样理解,磁盘上的一个分区,就是一个文件系统。这个就像我们在使用windows系统的时候,把磁盘分区可以格式化成FAT32,也可以格式成NTFS,这个完全自己来掌握,但所格式化的文件系统必需是你使用的系统所能认出来的。这就是为什么NTFS的文件系统,不能直接被Linux系统所认识。同样,windows也不能认识EXT3/Ext4一样的道理。
       Linux系统上常见文件系统格式有以下几个:
       EXT1:第一个受Linux支持的文件系统是Minix文件系统。这个文件系统有严重的性能问题,因此出现了另一个针对Linux的文件系统,即扩展文件系统。第1个扩展文件系统(ext1)由 Remy Card设计,并于 1992 年 4 月引入到 Linux 中。ext1文件系统是第一个使用虚拟文件系统(VFS)交换的文件系统。虚拟文件系统交换是在 0.96c 内核中实现的,支持的最大文件系统为2GB。
       EXT2:第 2 个扩展文件系统(ext2)也是由 Remy Card 实现的,并于 1993 年 1 月引入到 Linux 中。它借鉴了当时文件系统(比如 Berkeley Fast File System [FFS])的先进想法。ext2 支持的最大文件系统为 2TB,但是 2.6 内核将该文件系统支持的最大容量提升到 32TB。
       EXT3:第 3 个扩展文件系统(ext3)是 Linux 文件系统的重大改进,尽管它在性能方面逊色于某些竞争对手。ext3 文件系统引入了日志 概念,以在系统突然停止时提高文件系统的可靠性。虽然某些文件系统的性能更好(比如 Silicon Graphics 的 XFS 和 IBM® Journaled File System [JFS]),但 ext3 支持从使用 ext2 的系统进行就地(in-place)升级。ext3 由 Stephen Tweedie 实现,并于 2001 年 11 月引入。
       Ext4:2.6.28内核是首个稳定的 Ext4 文件系统。在性能、伸缩性和可靠性方面进行了大量改进。最值得一提的是,ext4 支持 1 EB 的文件系统。ext4 是由 Theodore Tso(ext3 的维护者)领导的开发团队实现的,并引入到 2.6.19 内核中。目前,它在 2.6.28 内核中已经很稳定(到 2008 年 12 月为止)。
swap: 它是Linux中一种专门用于交换分区的swap文件系统。Linux是使用这一整个分区作为交换空间。一般这个swap格式的交换分区是主内存的2倍。在内存不够时,Linux会将部分数据写到交换分区上。
 
2. 文件系统工作原理
 
       文件系统的工作与操作系统的文件数据有关。现在的操作系统的文件数据除了文件实际内容外,通常含有非常多的属性,例如文件权限(rwx)与文件属性(所有者、用户组、时间参数等)。文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放到inode中,数据则放到block区块中。另外,还有一个超级区块(super block)会记录整个文件系统的整体信息,包括 inode与block的总量、使用量、剩余量等。
每个 inode 与 block 都有编号,至于这三个数据的意义可以简略说明如下:
1、superblock:记录此 filesystem 的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式与相关信息等;
2、inode:记录文件的属性,一个文件占用一个inode,同时记录此文件的数据所在的 block 号码;
3、block:实际记录文件的内容,若文件太大时,会占用多个block。
       由于每个 inode 与 block 都有编号,而每个文件都会占用一个 inode ,inode 内则有文件数据放置的 block 号码。 因此,我们可以知道的是,如果能够找到文件的 inode 的话,那么自然就会知道这个文件所放置数据的 block 号码, 当然也就能够读出该文件的实际数据了。这是个比较有效率的作法,因为如此一来我们的磁盘就能够在短时间内读取出全部的数据,读写的效能比较好。
       我们将 inode 与 block 区块用图解来说明一下,如下图所示,文件系统先格式化出 inode 与 block 的区块,假设某一个档案的属性与权限数据是放置到 inode 3 号(下图较小方格内),而这个 inode 记录了档案数据的实际放置点为 2, 7, 13, 15 这四个 block 号码,此时我们的操作系统就能够据此来排列磁盘的阅读顺序,可以一口气将四个 block 内容读出来! 那么数据的读取就如同下图中的箭头所指定的模样了。
 

       这种数据存取的方法我们称为索引式文件系统(indexed allocation)。下面我们来看一下windows系统中的FAT,这种格式的文件系统并没有 inode 存在,所以 FAT 没有办法将这个文件的所有 block 在一开始就读取出来。每个 block 号码都记录在前一个 block 当中,读取方式如下所示:

 

       上图中我们假设文件的数据依序写入1->7->4->15号这四个 block 号码中,但这个文件系统没有办法一口气就知道四个 block 的号码,他得要一个一个的将 block 读出后,才会知道下一个 block 在何处。 如果同一个文件数据写入的 block 分散的太厉害时,则我们的磁盘读取头将无法在磁盘转一圈就读到所有的数据, 因此磁盘就会多转好几圈才能完整的读取到这个文件的内容。这就是为什么在windows系统中常常需要碎片整理, 需要碎片整理的原因就是文件写入的 block 太过于离散了,此时文件读取的效能将会变的很差。这个时候可以通过碎片整理将同一个文件所属的 blocks 汇整在一起,这样数据的读取会比较容易。

       FAT的文件系统需要不定期进行碎片整理,那么Ext是否需要磁盘整理呢?

       由于 Ext 是索引式文件系统,基本上不需要进行碎片整理。但是如果文件系统使用太久,常常删除/编辑/新增文件时,那么还是可能会造成文件数据太过于离散的问题,此时或许会需要进行重整一下的。不过,似乎没有多少人来进行Linux磁盘的碎片啊!

       如上所说的,inode 的内容在记录文件的权限与相关属性,至于 block 区块则是在记录文件的实际内容。 而且文件系统一开始就将 inode 与 block 规划好了,除非重新格式化(或者利用 resize2fs 等指令变更文件系统大小),否则 inode 与 block 固定后就不再变动。但是如果仔细考虑一下,如果我的文档系统高达数百GB时, 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定,因为 inode 与 block 的数量太庞大,不容易管理。 因此 Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 (block group) 的,每个区块群组都有独立的 inode/block/superblock 系统。 

 3. 文件系统结构

       Linux最传统的磁盘文件系统(filesystem)使用的是EXT2,所以要了解文件系统就得要由认识EXT2开始!在整体的规划当中,文件系统最前面有一个启动扇区(boot sector),这个启动扇区可以安装开机管理程序, 这是个非常重要的设计,这样我们就能够将不同的开机管理程序安装到个别的文件系统最前端,而不用覆盖整颗硬盘唯一的 MBR, 这样也才能够制作出多重引导的环境啊!至于每一个区块群组(block group)的六个主要内容说明如下:

      

 1、data block (资料区块)

data block 是用来放置文件内容数据地方,在 Ext2 文件系统中所支持的 block 大小有 1K, 2K 及 4K 三种而已。在格式化时 block 的大小就固定了,且每个 block 都有编号,以方便 inode 的记录啦。 不过要注意的是,由于 block 大小的差异,会导致该文件系统能够支持的最大磁盘容量与最大单一文件容量并不相同。 因为 block 大小而产生的 Ext2 文件系统限制如下图:

       虽然 Ext2 已经能够支持大于 2GB 以上的单一文件容量,不过某些应用程序依然使用旧的限制,也就是说,某些程序只能够捉到小于 2GB 以下的文件而已,这就跟文件系统无关了!原则上,block 的大小与数量在格式化完就不能够再改变了(除非重新格式化);每个 block 内最多只能够放置一个档案的数据;如果档案大于 block 的大小,则一个档案会占用多个 block 数量;若档案小于 block ,则该 block 的剩余容量就不能够再被使用了(磁盘空间会浪费);若档案很大的话,就会占用更多的block,将会降低文件系统的读写效能。

 2、inode table (inode 表格)
如前所述 inode 的内容在记录档案的属性以及该档案实际数据是放置在哪几号 block 内! 基本上,inode 记录的文件数据至少有底下这些:
 1该文件的存取模式(read/write/excute);
 2该文件的拥有者与群组(owner/group);
 3该文件的容量;
 4该文件建立或状态改变的时间(ctime);
 5最近一次的读取时间(atime);
 6最近修改的时间(mtime);
 7定义文件特性的旗标(flag),如 SetUID…;
 8该文件真正内容的指向 (pointer);
inode 的数量与大小也是在格式化时就已经固定了,除此之外 inode 还有以下特色:
 1每个 inode 大小均固定为 128 bytes;
 2每个文件都仅会占用一个 inode ;
 3文件系统能够建立的文件数量与 inode 的数量有关;
系统读取文件时需要先找到 inode,并分析 inode 所记录的权限与用户是否符合,若符合才能够开始实际读取 block 的内容。
3、Superblock (超级块)
Superblock 是记录整个 filesystem 相关信息的地方, 没有 Superblock ,就没有这个 filesystem 了。记录的信息主要有:
 1、block 与 inode 的总量;
 2、未使用与已使用的 inode / block 数量;
 3、block 与 inode 的大小 (block 为 1, 2, 4K,inode 为 128 bytes);
 4、filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘 (fsck) 的时间等文件系统的相关信息;
 一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0 ,若未被挂载,则 valid bit 为 1 。
Superblock 是非常重要的,因为我们这个文件系统的基本信息都写在这里。一般来说, superblock 的大小为 1024bytes。
4、Filesystem Description (文件系统描述说明)
这个区段可以描述每个 block group 的开始与结束的 block 号码,以及说明每个区段 (superblock, bitmap, inodemap, data block) 分别介于哪一个 block 号码之间。
5、block bitmap (区块对照表)
如果你想要新增文件时总会用到 block ,那要使用哪个 block 来记录呢?当然是选择空的block 来记录新文件的数据。 那你怎么知道哪个 block 是空的?这就得要透过 block bitmap 的辅助了。从 block bitmap 当中可以知道哪些 block 是空的,因此我们的系统就能够很快速的找到可使用的空间来处文件。同样的,如果你删除某些文件时,那么那些档案原本占用的 block 号码就得要释放出来, 此时在 block bitmap 当中相对应到该 block 号码的标志就得要修改成为未使用的,这就是 bitmap 的功能。
6、inode bitmap (inode 对照表)
这个其实与 block bitmap 是类似的功能,只是 block bitmap 记录的是使用与未使用的 block 号码, 至于 inode bitmap 则是记录使用与未使用的 inode 号码。