第7章Linux磁盘和文件系统管理

一、认识Linux文件系统

1.文件系统的特性

由于每种操作系统所设定的文档属性和权限并不相同,为了存放这些文件所需的数据,因此就需要将分区槽进行格式化,以成为操作系统能够利用的文件系统格式(文件系统)。

windows操作系统主要使用的是FAT和NTFS,而Linux主要是Ext2(Linuxsecondextended文件系统,ext2fs)。默认情况下,Windows是无法识别EXT2文件系统的。

现在LVM或软磁盘阵列可以将一个分区划分为多个文件系统,也可以将多个分区合成一个文件系统。所以目前格式化已经不再是针对分区而言,我们可以说一个可被挂载的数据为一个文件系统而不是一个分区

文件系统是如何运行的呢?较新的操作系统的文件数据除了文件实际内容外,通常含有非常多的属性,例如Linux操作系统的文件权限(rwx)与文件属性(拥有者、用户组、时间参数等)。文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到inode中,至于实际数据则放置到datablock区块中。另外,还有一个超级区块(superblock)会记录整个文件系统的整体信息,包括inode与block的总量、使用量、剩余量等。

每一个inode和block都要编号。inode、block、superblock的意义如下:

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

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

(3)block:实际记录文件的内容,如果文件过于大,会使用多个block。

我们将inode于block区块用图解来说明一下。如图1.1所示,文件系统先格式化出inode与block的区块,假设某一个文件的属性与权限数据是放置到inode4,而这个inode记录了文件数据的实际放置点为2,7,13,15这四个block编号,此时我们的操作系统就能够根据此来排列磁盘的阅读顺序将四个block内容读出来,数据的读取就如同下图中的箭头示。


图1.1inode和block的演示

这种数据存取方式被称为索引式文件系统(indexedallocation)。

例如FAT格式这种文件系统并没有inode的存在,所以它没有办法把所有的block一口气读出来,只能读完一个block,根据这个block中记录的编号去寻找下一个block。如果同一个文件数据写入的block太分散,磁盘读取头将无法在磁盘转一圈就读到所有的数据,因此磁盘就会多转好几圈才能完整的读取到这个文件的内容。我们常说的磁盘整理,原因就是因为文件写入的block太分散,会导致文件读取性能变差。解决方法就是通过碎片整理将同一个文件所属的blocks整理在一起

2.Ext2文件系统(inode

文件系统在最初就将inode和block规划好了,除非格式化,否则inode与block固定后就不再变动。但是若文件系统高达数百GB时,那么将inode和block放在一起并不合适,为此,Ext2文件系统在格式化的时候基本上是区分多个区块用户组(blockgroup)的,每个去看用户组都有自己的inode/superblock/block系统。如下图所示。

图1.2ext2文件系统示意图

系统最前面有一个启动扇区(bootsector),这个启动扇区可以安装开机管理程序,这个设计非常重要,通过这个扇区我们可将不同的开机管理程序安装到不同的文件系统最前面,而不是覆盖整个磁盘唯一的MBR,这样也才能够制作出多重引导的环境。

图1.2中每个BlockGroup里面都有6个部分,分别介绍如下:

(1)superblock(超级块)

它记录的信息主要有:

①block与inode的总量;

②未使用与已使用的inode/block数量;

③block与inode的大小(block为1,2,4K,inode为128bytes或256bytes);

④文件系统的挂载时间、最近一次写入数据的时间、最近一次检验磁盘(fsck)的时间等文件系统的相关信息;

④一个validbit数值,若此文件系统已被挂载,则validbit为0,若未被挂载,则validbit为1。

Superblock是非常重要的,因为我们这个文件系统的基本信息都写在这里,因此,如果superblock不存在了,你的文件系统可能就需要花费很多时间去恢复。一般来说,superblock的大小为1024bytes

此外,每个blockgroup都可能含有superblock。但是我们也说一个文件系统应该仅有一个superblock而已,那是怎么回事啊?事实上除了第一个blockgroup内会含有superblock之外,后续的blockgroup不一定含有superblock,如果它含有,则该superblock主要是做为第一个blockgroup内superblock的备份。

(2)文件系统Description(文件系统描述说明)

这个部分描述每个blockgroup的开始与结束的Blcok编码,同时说明每个区段(superblock/bitmap/inodemap/datablock)分别介于哪一个block编码之间。

(3)blockbitmap(区块对照表)

blockbitmap中记录着哪些block是空的,哪些block是使用中的。

(4)inodebitmap(inode对照表)

这个是记录使用与未使用的inode的编号。

(5)inodetable(inode表格)

inode记录的文件数据至少有以下几项:

①该文件的存取模式(read/write/excute);

②该文件的拥有者与用户组(owner/group);

③该文件的容量;

④该文件建立或状态改变的时间(ctime);

⑤最近一次的读取时间(atime);

⑥最近修改的时间(mtime);

⑦定义文件特性的标志(flag),如SetUID等;

⑧该文件真正内容的指向(pointer)。

inode的数量和大小也是在格式化时就已经固定另外它还有以下特点:

①每个inode大小均固定为128bytes(新的ext4与xfs可设定到256bytes);

②每个文件都仅会占用一个inode而已,因此文件系统能够建立的文件数量与inode的数量有关;

③系统读取文件时需要先找到inode,并分析inode所记录的权限与用户是否符合,若符合才能够开始实际读取block的内容。

接下来,以EXT2为例来分析下inode和block的关系。inode大小为128bytes,其中block号码需要4bytes,假如我们有一个400MB的文件,且每个block为4k,那么我们需要记录10W个block号码,128bytes是远远不够的。为了解决这一问题,inode记录block编号的区域被定义为了12个直接、1个间接、1个双间接、1个三间接的记录区,如图1.3所示。

图1.3inode记录block的区域

上图中的inode最上面是记录文件权限和属性的地方,下面就是12个直接指向block区域的编号。下面一个就是所谓的间接区,它就是拿一个block来当作记录block号码的记录区,如果文件太大的时候,就会使用间接的block来记录编号,当文件持续增大,就会使用双间接乃至三间接。

假设我们的block大小为1k,那么就可以有以下的情况:

①12个直接:12*1K=12K。直接指向,故可指向12个block。

②一个间接:256*1K=256K。由于间接区利用一个block来记录block编号,每个编号4bytes,所以可以记录256个编号。

③双间接:256*256*1K=65536K。双间接的第一层有256个区,第二层有256个区。

④三间接:256*256*256*1K=16777216K=16384MB=16G。如(3)同理。

⑤总额:12+256+256*256+256*256*256(K)≈16G。

(6)datablock(数据块)

datablock是放置文件内容数据的地方,在EXT2中所支持的block大小有1K2K4K。因block大小而产生的EXT2文件系统限制如下:

Block大小1KB2KB4KB
最大单一文件限制16GB256B2TB
最大文件系统总容量2TB8TB16TB

block块有以下特点:

①原则上,block的大小与数量在格式化完就不能够再改变了(除非重新格式化);

②每个block内最多只能够放置一个文件的数据;

③如果文件大于block的大小,则一个文件会占用多个block数量;若文件小于block,则该block的剩余容量就不能够再被使用了(磁盘空间会浪费)。

每个区段与superblock的信息都可以使用dumpe2fs这个命令来查询。

[root@study~]#dumpe2fs[-bh]设备文件名

选项与参数:

-b:列出保留为坏道的部分。

-h:仅列出superblock的数据,不会列出其他的区段内容。

3.与目录树的关系

(1)目录

当我们在Linux下的文件系统建立一个目录时,文件系统会分配一个inode与至少一个block给该目录。其中,inode记录该目录的相关权限与属性,并可记录分配到的那个block号码,而block则是记录在这个目录下的文件名与文件名占用的inode号码信息。也就是说目录所占用的块内容在记录如下的信息:

Inodenumber文件名
53735697

53745858

anaconda-ks.cfg

initial-setup-ks.cfg

(2)文件

当我们在Linux下的ext2建立一个一般文件时,ext2会分配一个inode与相对于该文件大小合适的数量的block给该文件。

(4)文件系统大小与磁盘读取性能

虽然我们的ext2在inode处已经将该文件所记录的block号码做记录,数据可以一次性读取,但是如果文件真的太过分散,还是会发生读取效率低的问题。因为硬盘读取头还是得要在整个文件系统中来回读取。因此,我们可以将整个内的资料全部复制出来,将该文件系统重新格式化,再将资料复制回去即可解决这个问题。

此外,如果文件系统真的太大了,那么当一个文件分别记录在这个文件系统的最前面与最后面的block号码中,此时会造成硬盘的机械手臂移动幅度过大,也会造成资料读取性能的下降,而且读取头在搜寻整个文件系统时,也会花费比较多的时间去搜索。因此,分区的规划并不是越大越好,而是真的要针对您的主机用途来进行规划才可以。

4.EXT2/EXT3/EXT4文件的存取与日志式文件系统的功能

如果我们需要新建一个文件/目录,文件系统又是怎么处理的呢?这里就需要使用blockbitmap和inodebitmap了。假设我们要新增一个文件,那么文件系统将要做以下事情:

①先确定用户对于欲新增文件的目录是否具有w与x的权限,若有则继续往下,否则停止;

②根据inodebitmap找到没有使用的inode号码,并将新文件的权限/属性写入;

③根据blockbitmap找到没有使用的block号码,并将实际的数据写入block中,且更新inode的block指向数据;

④将刚刚写入的inode与block数据同步更新inodebitmap与blockbitmap,并更新superblock的内容。

一般来说,我们将inodetable与datablock称为数据存放区域,至于其他例如superblock、blockbitmap与inodebitmap等区段就被称为metadata(中间数据)。这是因为superblock,inodebitmap及blockbitmap的数据是经常变动的,每次新增、移除、编辑时都可能会影响到这三个部分的数据,因此才被称为中间数据。

(1)数据的不一致(Inconsistent)状态

如果文件在写入系统的时候,因突发原因导致出错,所写入数据只有inodetable和datablock,最后一个同步更新metadata的过程并没有完成,就会出现metadata内容与实际数据存放区不一致的情况。

在早期的EXT2系统中,系统在重新启动的时候,会有superblock中的vaildbit(是否有挂载)和文件系统state(clean与否)等状态来判断是否强制进行数据一致性检验,若有需要检查可以以e2fsck来进行。不过若文件系统极大,这样将非常耗时,日志式文件系统应运而生。

(2)日志式文件系统

所谓日志式文件系统是指,在文件系统中规划处一个区块专门记录写入或修订文件时的步骤,它主要分为3个过程:

①预备:当系统要写入一个文件时,会先在日志记录区块中记录某个文件准备要写入的信息;

②实际写入:开始写入文件的权限与数据;开始更新metadata的数据;

③结束:完成数据与metadata的更新后,在日志记录区块当中完成该文件的记录。

5.Linux文件系统的操作

为了解决编辑较大文件时,磁盘写入速度要慢于内存速度的问题,Linux采用的是异步处理(asynchronously)方式。

这种方式是:当系统载入一个文件到内存后,如果该文件没有被更动过,则在内存区段的文件数据会被设定为干净(clean)的。但如果内存中的文件数据被更改过了,此时该内存中的数据会被设定为脏的(Dirty)。此时所有的动作都还在内存中执行,并没有写入到磁盘中。

另外,Linux系统的文件系统与内存的互动有以下几点:

①系统会不定时的将内存中设定为“Dirty”的数据写回磁盘,以保持磁盘与内存数据的一致性。

②系统会将常用的文件数据放置到主存储器的缓冲区,以加速文件系统的读/写。但这样Linux的物理内存最后都会被用光,不过这是正常的情况,它可加速系统效能。

③你可以手动使用sync来强迫内存中设定为“Dirty”的文件回写到磁盘中;

④若正常关机时,关机指令会主动呼叫sync来将内存的数据回写入磁盘内;

⑤但若不正常关机(如停电、死机或其他不明原因),由于数据尚未回写到磁盘内,因此重新启动后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)。

6.挂载点的意义

将文件系统与目录树的结合称为“挂载”。挂载点一定是目录,该目录为进入该文件系统的入口。必须挂载到目录树的某个目录后,文件系统才能被正常使用。

7.其它Linux支持的文件系统与VFS

Linux核心是怎样管理这些认识的文件系统呢?其实Linux是通过名为Virtual 文件系统 Switch的核心功能去读取文件系统的。

8.XFS文件系统

XFS就是一个日志式文件系统。XFS文件系统在数据分布上,分为数据区(data section文件系统活动登录区(log section实时运行区(realtime section。它们的内容如下:

(1)数据区

也包括inode/data block/superbloc等数据,也是分为多个存储区群组来分别放置文件系统所需要的数据,每个存储区组包括了:整个文件系统的superblock、剩余空间的管理机制、inode分配与追踪。此外,inode与block都是系统用到的时候才动态配置产生。

另外,EXT不同的是,xfsblockinode有多种不同容量可以设置,block容量可以在512bytes~64KB之间调整(Linux环境下最高位4K),inode256bytes2M之间

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

记录文件系统的变化,直到该变化完整的写入到数据区后,该次记录才会结束。因为系统所有动作的时候都会在这个区块做记录,因此这个区块的活动相当频繁。xfs允许用户指定外部磁盘来作为xfs文件系统的日志区块。

(3)实时运行区

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

xfs可以使用xfs_info去观察superblock内容。