Linux最传统的磁盘文件系统(file system)使用的是EXT2/所有要了解文件系统就得要由认识EXT2开始。而文件系统是创建在硬盘上面的,因为我们的了解硬盘的物理组成。
###硬盘组成与分区
整块磁盘的组成主要有:
- 圆形的盘片(主要记录数据的部分);
- 机械手臂与机械手臂上的磁头(可读写盘片上的数据);
- 主轴马达,可转动盘片,让机械手臂的磁头在盘片上读写数据。
从上面我们知道数据存储与读取的重点在于盘片,而盘片的物理组成则为:
- 扇区(Sector)为最小的物理存储单位,且依据磁盘设计的不同,目前主要有每个扇区为512bytes与4K两种格式;
- 将扇区组成一个圆,那就是柱面(Cylinder),早期的分区主要以柱面为最小分区(partition)单位,现在的分区通常使用扇区为最小分区单位;
- 磁盘分区表主要有两种格式,一种是限制较多的MBR分区表,一种是较新且限制较少的GPT分区表。
- MBR分区表中,第一个扇区最重要,里面有:(1) 主要开机区(Master boot record, MBR)及分区表(partition table),其中MBR占有446Bytes,而partition table则占有64Bytes。
- GPT分区表除了分区数量扩充较多外,支持的磁盘容量也可以超过2TB。
各种接口的磁盘在Linux中的文件名分别为:
- /dev/sd[a-p][1-128]:为SCSI,SATA,USB,FLASH等接口的磁盘文件名;
- /dev/hd[a-d][1-63]:为IDE接口的磁盘文件名。
- /dev/vd[a-d][1-128]: 为虚拟磁盘的磁盘文件名
- /dev/md[0-128] : 软件磁盘阵列
- /dev/VGNAME/LVNAME : LVM
MBR分区表最多只能记录四条分区的记录,这四条记录我们称为主(primary)分区或扩展(extended)分区,其中扩展分区还可以再分成逻辑分区(logical),而能被格式化的则仅有分区与逻辑分区而已。
分区的定义:
- 主分区与扩展分区最多可以有4个(硬盘的限制);
- 扩展分区最多只能有一个(操作系统的限制);
- 逻辑分区是由扩展分区持续分出来的分区;
- 能够被格式化后作为数据访问的分区为主要分区与逻辑分区,扩展分区无法格式化;
- 逻辑分区的数量依操作系统而不同,在Linux系统中,IDE硬盘最多有59个逻辑分区(5号到63号),SATA硬盘则有11个逻辑分区(5号到15号)。
文件系统特性
磁盘分区完毕后还需要进行格式化(format),之后操作系统才能够使用这个分区。为什么要格式化?这是因为每种操作系统设置的文件属性/权限并不相同,为了存放这些文件所需的数据,因此就需要将分区进行格式化,以称为操作系统能够利用的文件系统格式。
由此可知,每种操作系统能够使用的文件系统并不相同。windows 98以前主要的文件系统为FAT(或FAT16),windows 2000以后为NTFS文件系统,而Linux的正规文件系统为Ext2(Linux second extended file system, Ext2fs)这一个。
通常我们称呼一个可被挂载的数据为一个文件系统而不是一个分区。
Linux操作系统的文件权限(rwx)与文件属性(所有者、群组、时间参数)。文件系统通常会将这两部分的数据分别放在不同的块,权限与属性放置在inode中,至于实际数据则放置到data block块中。另外还有一个超级块(super block)会记录整个文件系统的整体信息,包括inode与block的总量、使用量、剩余量等。
super block、inode、block的意义说明如下: *super block:记录此文件系统的整体信息,包括inode/block的总量、使用量、剩余量,以及文件系统的格式与相关信息等;
-
block:实际记录文件的内容,若文件太大时,会占用多个block。 每个inode与block都有编号,而每个文件都会占用一个inode,inode内则有文件数据放置的inode号码。
这种访问方式我们称为索引式文件系统(indexed allocation)。
Linux的Ext2文件系统(inode)
文件系统一开始就将inode与block规划好了,除非重新格式化(或者利用resize2fs等命令更改文件系统大小),否则inode与block固定后就不再变动。
Ext2文件系统在格式化的时候基本上是区分为多个块组(block group)的,每个块组都有独立的inode/block/super block系统。
在整体的规划中,文件系统最前面有一个启动扇区(boot sector),整个启动扇区可以安装引导装载程度,每个块组的6个主要内容说明如下:
- data block(数据块)
- data block是用来放置文件内容地方,在Ext2文件系统中所支持的block大小有1kb、2kb、4kb三种。在格式化时block大小就固定了,且每个block都有编号,以方便inode的记录。由于block大小的区别,会导致文件系统能够支持的最大磁盘容量与最大单一文件并不相同。限制如下 |Block大小|1KB|2KB|4KB| |--|--|--|--| |最大单一文件限制|16GB|256GB|2TB| |最大文件系统总容量|2TB|8TB|16TB| block的基本限制如下:
- 原则上,block的大小与数量在格式化完就不能够再改变了(除非重新格式化)。
- 每个block内最多只能够放置一个文件的数据。
- 承上,如果文件大于block的大小,则一个文件会占用多个block数量;
- 承上,若文件小于block,则该block的剩余空间就不能够再被使用了(磁盘空间会浪费)。
-
inode table(inode表格)
- inode记录的文件数据至少如下:
- 该文件的访问模式(read/write/excute);
- 该文件的所有者与组(owner/group);
- 该文件的大小;
- 该文件创建或状态改变的时间(ctime);
- 最近一次的读取时间(atime);
- 最近修改的时间(mtime);
- 定义文件特性的标志(flag),如SetUID等;
- 该文件真正内容的指向(pointer)。
- 除此之外的特色:
- 每个inode大小均固定为128bytes(新的ext4与xfs可设置到256Bytes);
- 每个文件都仅会占用一个inode而已;
- 承上,因此文件系统能够创建的文件数量与inode的数量有关;
- 系统读取文件时需要先找到inode,并分析inode所记录的权限与用户是否符合,若符合才能够开始实际读取block的内容。
-
分析依稀inode/block与文件大小的关系。inode记录block的区域定义为12个直接、一个间接、一个双间接与一个三间接记录区。
-
Superblock(超级块)
- Superblock是记录整个文件系统相关信息的地方,记录的主要信息有:
- block与inode的总量;
- 未使用与已使用的inode/block数量;
- block与inode的大小(block未1K,2K,4K,inode为128bytes或256Bytes);
- 文件系统的挂载时间、最近一次写入数据的时间、最近一次检验磁盘(fsck)的时间等文件系统的相关信息;
- 一个valid bit数值,若此文件系统已被挂载,则valid bit为0,若未被挂载,则valid bit未1。
superblock是非常重要的,因为文件系统的基本信息都写在这里,superblock的大小为1024Bytes。
此外,每个block group都可能含有superblock,但是我们也说一个文件系统应该仅有一个superblock而已,因为除了第一个block group内会含有superblock之外,后续的block group不一定含有superblock,而若含有superblock则该superblcok主要是作为第一个block group内的superblock的备份。
- Filesystem Description (文件系统描述说明)
这个区段可以描述每个block group的开始与结束的block号码,以及说明每个区段(superblock, bitmap, inodemap, data block)分别介于哪一个block号码之间。
- block bitmap(块对照表)
- 从block bitmap当中可以知道哪些block是空的。
- inode bitmap(inode对照表)
- 与block bitmap功能类似。
与目录树的关系
每个文件(不管是一般文件还是目录文件)都 会占用一个 inode , 且可依据文件内容的大小来分配多个 block 给该文件使用。我们知道目录的内容在记录文件名, 一般文件才是实际记录数据内容的地方。 那么目录与文件在文件系统当中是如何记录数据的呢?基本上可以这样说:
- 目录
当我们在 Linux 下的文件系统创建一个目录时,文件系统会分配一个 inode 与至少一块 block 给该目录。其中,inode 记录该目录的相关权限与属性,并可记录分配到的那块 block 号码; 而 block 则是记录在这个目录下的文件名与该文件名占用的 inode 号码数据。也就是说目录所 占用的 block 内容在记录如下的信息:
- 文件
在 Linux 下的 ext2 创建一个一般文件时, ext2 会分配一个 inode 与相对于该文件大小 的 block 数量给该文件。
- 目录树读取
我们知道 inode 本身并不记录文件名,文件名的记录是在目录的 block 当中。
因此“新增/删除/ 更名文件名与目录的 w 权限有关” 那么因为文件名是记录在目录的 block 当中, 因此当要读取某个文件时,就务必会经过目录的 inode 与 block ,然后才能够找到那个待读取 文件的 inode 号码, 最终才会读到正确的文件的 block 内的数据。
由于目录树是由根目录开始读起,因此系统通过挂载的信息可以找到挂载点的 inode 号码, 此时就能够得到根目录的 inode 内容,并依据该 inode 读取根目录的 block 内的文件名数据, 再一层一层的往下读到正确的文件名。举例来说,如果我想要读取 /etc/passwd 这个文件时, 系统是如何读取的呢?
[root@study ~]# ll -di / /etc /etc/passwd
128 dr-xr-xr-x. 17 root root 4096 May 4 17:56 /
33595521 drwxr-xr-x. 131 root root 8192 Jun 17 00:20 /etc
36628004 -rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd
该文件的读取流程为 (假设读取者身份为一般身份使用者):
- /的inode:通过挂载点的信息找到inode号码为128的根目录inode,且inode规范的 权限让我们可以读取该 block 的内容(有 r 与 x) ;
- /的block:经过上个步骤取得block的号码,并找到该内容有etc/目录的inode号码 (33595521);
- etc/的inode:读取33595521号inode得知dmtsai具有r与x的权限,因此可以读取 etc/ 的 block 内容;
- etc/的block:经过上个步骤取得block号码,并找到该内容有passwd文件的inode号 码 (36628004);
- passwd的inode:读取36628004号inode得知dmtsai具有r的权限,因此可以读取 passwd 的 block 内容;
- passwd的block:最后将该block内容的数据读出来。
EXT2/EXT3/EXT4文件的存取与日志式文件系统的功能
假设我们想要新增一个 文件,此时文件系统的行为是:
- 先确定使用者对于欲新增文件的目录是否具有w与x的权限,若有的话才能新增;
- 根据inodebitmap找到没有使用的inode号码,并将新文件的权限/属性写入;
- 根据blockbitmap找到没有使用中的block号码,并将实际的数据写入block中,且更新 inode 的 block 指向数据;
- 将刚刚写入的inode与block数据同步更新inodebitmap与blockbitmap,并更新superblock 的内容。
一般来说,我们将 inode table 与 data block 称为数据存放区域,至于其他例如 superblock、 block bitmap 与 inode bitmap 等区段就被称为 metadata (中介数据) ,因为 superblock, inode bitmap 及 block bitmap 的数据是经常变动的,每次新增、移除、编辑时都可能会影响 到这三个部分的数据,因此才被称为中介数据。
- 数据的不一致(inconsistent)状态
如果文件在写入文件系统时,因为不知名原因导致系统中断,写入的数据仅有 inode table 及 data block 而已, 最后一个同步更新中介数据的步骤并没有做完,此时就会发生 metadata 的内容与实际数据存放区产生不一致 (Inconsistent) 的情况了。
在早期的 Ext2 文件系统中,如果发生这个问题,那么系统在 重新开机的时候,就会借由 Superblock 当中记录的valid bit (是否有挂载) 与 filesystem state (clean 与否) 等状态来判断是否强制进行数据一致性的检查!若有需要检查时则以 e2fsck 这支程序来进行的。
- 日志式文件系统(Journaling filesystem)
为了避免文件系统不一致的情况发生,在filesystem当中规划出一个区块,该区块专门在记录写入或修订文件时的步骤,也就是说:
- 预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;
- 实际写入:开始写入文件的权限与数据;开始更新metadata的数据;
- 结束:完成数据与metadata的更新后,在日志记录区块当中完成该文件的纪录。
Linux文件系统的运行
所有的数据 都得要载入到内存后 CPU 才能够对该数据进行处理。如果你常常编辑一个好大的文件,在编辑的过程中又频繁的写入到磁盘中,由于磁盘写入的速度要比内存慢多, 因此会常常耗在等待磁盘的写入/读取上。
为了解决这个效率的问题,因此Linux使用的方式是通过一个称为非同步处理 (asynchronously) 的方式。所谓的非同步处理是这样的:
当系统载入一个文件到内存后,如果该文件没有被更动过,则在内存区段的文件数据会被设 置为干净(clean)的。 但如果内存中的文件数据被更改过了,此时该内存中的数据会被设置为脏的 (Dirty)。此时所有的动作都还在内存中执 行,并没有写入到磁盘中! 系统会不定时的将内存中设置为“Dirty”的数据写回磁盘,以保持 磁盘与内存数据的一致性。
Linux 系统上面文件系统与内存有非 常大的关系:
- 系统会将常用的文件数据放置到内存的缓冲区,以加速文件系统的读/写;
- 承上,因此 Linux 的实体内存最后都会被用光!这是正常的情况!可加速系统性能;
- 你可以手动使用 sync 来强迫内存中设置为 Dirty 的文件回写到磁盘中;
- 若正常关机时,关机指令会主动调用 sync 来将内存的数据回写入磁盘内;
- 但若不正常关机(如跳电、死机或其他不明原因),由于数据尚未回写到磁盘内, 因此 重新开机后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘 损毁)。
挂载点的意义(mount point)
将文件系统与目录树结合的动作我们称为“挂载”。重点是:挂载点一定是目录,该目录为进入该文件系统的入口。因此并不是你有任何文件系统都能使用,必须要“挂载”到目录树的某个目录后,才能够使用该文件系统。
其他Linux支持的文件系统与VFS
常见的支持文件系统有:
-
传统文件系统:ext2/minix/MS-DOS/FAT(用vfat模块)/iso9660(光盘)
-
日志式文件系统:ext3/ext4/reiserFS/Windows'NTFS/IBM's JFS/SGI's XFS/ZFS
-
网络文件系统: NFS/SMBFS
-
Linux VFS (Virtual Filesystem Switch)
整个Linux的系统都是通过一个名为Virtual Filesystem Switch的核心功能去读取filesystem,也就是说,整个Linux认识的filesystem其实都是VFS在进行管理,我们使用者并不需要知道每个partition上头的filesystem是什么。
XFS文件系统简介
- EXT家族当前伤脑筋的地方:支持度最广,但格式化超慢
Ext 文件系统家族对于文件格式化的处理方面,采用的是预先规划出所有的 inode/block/meta data 等数据,未来系统可以直接取用, 不需要再进行动态配置的作法。当你的 TB 以上等级的传统 ext 家族文件 系统在格式化的时候,光是系统要预先分配 inode 与 block 就消耗你好多好多的人类时间了
- XFS 文件系统的配置
基本上xfs就是一个日志式文件系统,而CentOS 7.x拿它当默认的文件系统,自然就是因为最早之前,这个 xfs就是被开发来用于大容量磁盘以及高性能文件系统之用,因此,相当适 合现在的系统环境。此外,几乎所有Ext4文件系统有的功能,xfs 都可以具备!
xfs文件系统在数据的分布上,主要规划为三个部份,一个数据区 (data section)、一个文件系统活动登录区 (log section)以及一个实时运行区 (realtime section)。 这三个区域的 数据内容如下:
- 数据区(data section)
数据区就跟我们之前谈到的 ext 家族一样,包括 inode/data block/superblock 等数据,都放置在这个区块。 这个数据区与 ext 家族的 block group 类似,也是分为多个储存区群 组 (allocation groups) 来分别放置文件系统所需要的数据。 每个储存区群组都包含了 (1)整个文件系统的 superblock、 (2)剩余空间的管理机制、 (3)inode的分配与追踪。此外,inode与 block 都是系统需要用到时,这才动态配置产生,所以格式化动作超级快。
另外,与 ext 家族不同的是, xfs 的 block 与 inode 有多种不同的容量可供设置,block 容量 可由 512Bytes ~ 64K 调配,不过,Linux 的环境下, 由于内存控制的关系,因此最高可以使用的 block 大小为 4K 而已! 至于 inode 容量可由 256Bytes 到 2M 这么大!不过,大概还是保留 256Bytes 的默认 值就很够用了!
- 文件系统活动登录区(log section)
在登录区整个区域主要用来记录文件系统的变化,其实有点像是日志区。文件的变化会在这里记录下来,直到该变化完整的写入数据区后,该笔记录才会被终结。如果文件系统因为某些缘故而损毁,系统就会拿这个登录区块来进行检验,看看系统挂掉之前,文件系统正在运行啥动作,借以快速的修复文件系统。
- 实时运行区(realtime section)
当有文件要被创建时,xfs会在这个区段里面找一个数个的extent区块,将文件放置在这个区块内,等分配完毕后,在写入到data section的inode与block去。这个event区块的大小得要在格式化的时候先指定,最小值是4K最大可到1G,一般非磁盘阵列的磁盘默认为64K容量,而具有类似磁盘阵列的stripe情况下,则建议extent设置为与stripe一样大较佳。