系统管理员很重要的任务之一就是管理好自己的磁盘文件系统, 每个分区不可太大也不能太小, 太大会造成磁盘容量的浪费, 太小则会产生文件无法储存的困扰。 前面谈到的文件权限与属性中, 这些权限与属性分别记录在文件系统的哪个区块内? 这就得要
谈到 filesystem 中的 inode 与 block 了。 同时, 为了虚拟化与大容量磁盘, 现在的 CentOS 7默认使用大容量性能较佳的 xfs 当默认文件系统了! 这也得了解一下。 此章节我们的重点在于如何制作文件系统, 包括分区、 格式化与挂载等, 是很重要的一个章节
磁盘的组成与分区
首先说明一下磁盘的物理组成, 整颗磁盘的组成主要有:
- 圆形的盘片( 主要记录数据的部分) ;
- 机械手臂, 与在机械手臂上的磁头( 可读写盘片上的数据) ;
- 主轴马达, 可以转动盘片, 让机械手臂的磁头在盘片上读写数据。
上面我们知道数据储存与读取的重点在于盘片, 而盘片上的物理组成则为( 假设此磁盘为单碟片
- 扇区( Sector) 为最小的物理储存单位, 且依据磁盘设计的不同, 目前主要有 512Bytes与 4K 两种格式;
- 将扇区组成一个圆, 那就是柱面( Cylinder) ;
- 早期的分区主要以柱面为最小分区单位, 现在的分区通常使用扇区为最小分区单位( 每个扇区都有其号码喔, 就好像座位一样) ;
- 磁盘分区表主要有两种格式, 一种是限制较多的 MBR 分区表, 一种是较新且限制较少的GPT 分区表。
- MBR 分区表中, 第一个扇区最重要, 里面有: ( 1) 主要开机区( Master boot record,MBR) 及分区表( partition table) , 其中 MBR 占有 446 Bytes, 而 partition table 则占有 64 Bytes.
- GPT 分区表除了分区数量扩充较多之外, 支持的磁盘容量也可以超过 2TB。
至于磁盘的文件名部份, 基本上, 所有实体磁盘的文件名都已经被仿真成 /dev/sd[a-p] 的格式, 第一颗磁盘文件名为 /dev/sda。 而分区的文件名若以第一颗磁盘为例, 则为 /dev/sda[1-128] 。 除了实体磁盘之外, 虚拟机的磁盘通常为 /dev/vd[a-p] 的格式。 若有使用到软件磁盘阵列的话, 那还有 /dev/md[0-128] 的磁盘文件名。 使用的是 LVM 时, 文件名则为/dev/VGNAME/LVNAME 等格式
- /dev/sd[a-p][1-128]: 为实体磁盘的磁盘文件名;
- /dev/vd[a-d][1-128]: 为虚拟磁盘的磁盘文件名
复习完物理组成后, 来复习一下磁盘分区吧! 如前所述, 以前磁盘分区最小单位经常是柱面, 但 CentOS 7 的分区软件, 已经将最小单位改成扇区了, 所以容量大小的分区可以切的更细~此外, 由于新的大容量磁盘大多得要使用 GPT 分区表才能够使用全部的容量, 因此过去那个 MBR 的传统磁盘分区表限制就不会存在了。 不过, 由于还是有小磁盘啊! 因此, 你在处理分区的时候, 还是得要先查询一下, 你的分区是 MBR 的分区? 还是 GPT 的分区?鸟哥建议过强制使用 GPT 分区喔! 所以本章后续的动作, 大多还是以 GPT 为主来介绍
文件系统特性
我们都知道磁盘分区完毕后还需要进行格式化( format) , 之后操作系统才能够使用这个文件系统。 为什么需要进行“格式化”呢? 这是因为每种操作系统所设置的文件属性/权限并不相同, 为了存放这些文件所需的数据, 因此就需要将分区进行格式化, 以成为操作系统能够利用的“文件系统格式( filesystem) ”。
由此我们也能够知道, 每种操作系统能够使用的文件系统并不相同。 举例来说, windows 98以前的微软操作系统主要利用的文件系统是 FAT ( 或 FAT16) , windows 2000 以后的版本有所谓的 NTFS 文件系统, 至于 Linux 的正统文件系统则为 Ext2 ( Linux second extended file system, ext2fs) 这一个。 此外, 在默认的情况下, windows 操作系统是不会认识 Linux的 Ext2 的。
传统的磁盘与文件系统之应用中, 一个分区就是只能够被格式化成为一个文件系统, 所以我们可以说一个 filesystem 就是一个 partition。 但是由于新技术的利用, 例如我们常听到的LVM与软件磁盘阵列( software raid) , 这些技术可以将一个分区格式化为多个文件系统( 例如LVM) , 也能够将多个分区合成一个文件系统( LVM, RAID) ! 所以说, 目前我们在格式化时已经不再说成针对 partition 来格式化了, 通常我们可以称呼一个可被挂载的数据为一个文件系统而不是一个分区喔!
那么文件系统是如何运行的呢? 这与操作系统的文件数据有关。 较新的操作系统的文件数据除了文件实际内容外, 通常含有非常多的属性, 例如 Linux 操作系统的文件权限( rwx) 与文件属性( 拥有者、 群组、 时间参数等) 。 文件系统通常会将这两部份的数据分别存放在不同的区块, 权限与属性放置到 inode 中, 至于实际数据则放置到 data block 区块中。 另外, 还有一个超级区块 ( superblock) 会记录整个文件系统的整体信息, 包括 inode 与 block 的总量、 使用量、 剩余量等。
每个 inode 与 block 都有编号, 至于这三个数据的意义可以简略说明如下:
- superblock: 记录此 filesystem 的整体信息, 包括inode/block的总量、 使用量、 剩余量,以及文件系统的格式与相关信息等;
- inode: 记录文件的属性, 一个文件占用一个inode, 同时记录此文件的数据所在的 block号码;
- block: 实际记录文件的内容, 若文件太大时, 会占用多个 block
由于每个 inode 与 block 都有编号, 而每个文件都会占用一个 inode , inode 内则有文件数据放置的 block 号码。 因此, 我们可以知道的是, 如果能够找到文件的 inode 的话, 那么自然就会知道这个文件所放置数据的 block 号码, 当然也就能够读出该文件的实际数据了。 这是个比较有效率的作法, 因为如此一来我们的磁盘就能够在短时间内读取出全部的数据, 读写的性能比较好啰。
我们将 inode 与 block 区块用图解来说明一下, 如下图所示, 文件系统先格式化出 inode 与block 的区块, 假设某一个文件的属性与权限数据是放置到 inode 4 号( 下图较小方格内) ,而这个 inode 记录了文件数据的实际放置点为 2, 7, 13, 15 这四个 block 号码, 此时我们的操作系统就能够据此来排列磁盘的读取顺序, 可以一口气将四个 block 内容读出来! 那么数据的读取就如同下图中的箭头所指定的模样了。
这种数据存取的方法我们称为索引式文件系统( indexed allocation) 。 那有没有其他的惯用文件系统可以比较一下啊? 有的, 那就是我们惯用的U盘( 闪存) , U盘使用的文件系统一般为 FAT 格式。 FAT 这种格式的文件系统并没有 inode 存在, 所以 FAT 没有办法将这个文件的所有 block 在一开始就读取出来。 每个 block 号码都记录在前一个 block 当中, 他的读取方式有点像下面这样:
上图中我们假设文件的数据依序写入1->7->4->15号这四个 block 号码中, 但这个文件系统没有办法一口气就知道四个 block 的号码, 他得要一个一个的将 block 读出后, 才会知道下一个block 在何处。 如果同一个文件数据写入的 block 分散的太过厉害时, 则我们的磁头将无法在磁盘转一圈就读到所有的数据, 因此磁盘就会多转好几圈才能完整的读取到这个文件的内容!
常常会听到所谓的“磁盘重组”吧? 需要磁盘重组的原因就是文件写入的 block 太过于离散了,此时文件读取的性能将会变的很差所致。 这个时候可以通过磁盘重组将同一个文件所属的blocks 汇整在一起, 这样数据的读取会比较容易啊! 想当然尔, FAT 的文件系统需要三不五时的磁盘重组一下, 那么 Ext2 是否需要磁盘重整呢?
由于 Ext2 是索引式文件系统, 基本上不太需要常常进行磁盘重组的。 但是如果文件系统使用太久, 常常删除/编辑/新增文件时, 那么还是可能会造成文件数据太过于离散的问题, 此时或许会需要进行重整一下的。 不过, 老实说, 鸟哥倒是没有在 Linux 操作系统上面进行过Ext2/Ext3 文件系统的磁盘重组说! 似乎不太需要啦!
Linux的EXT2文件系统(incode)
在第五章当中我们介绍过 Linux 的文件除了原有的数据内容外, 还含有非常多的权限与属性, 这些权限与属性是为了保护每个使用者所拥有数据的隐密性。 而前一小节我们知道filesystem 里面可能含有的 inode/block/superblock 等。 为什么要谈这个呢? 因为标准的Linux 文件系统 Ext2 就是使用这种 inode 为基础的文件系统啦!
而如同前一小节所说的, inode 的内容在记录文件的权限与相关属性, 至于 block 区块则是在记录文件的实际内容。 而且文件系统一开始就将 inode 与 block 规划好了, 除非重新格式化( 或者利用 resize2fs 等指令变更文件系统大小) , 否则 inode 与 block 固定后就不再变动。但是如果仔细考虑一下, 如果我的文件系统高达数百GB时, 那么将所有的 inode 与 block 通通放置在一起将是很不智的决定, 因为 inode 与 block 的数量太庞大, 不容易管理。
为此之故, 因此 Ext2 文件系统在格式化的时候基本上是区分为多个区块群组 ( block group) 的, 每个区块群组都有独立的 inode/block/superblock 系统。 感觉上就好像我们在当兵时, 一个营里面有分成数个连, 每个连有自己的联络系统, 但最终都向营部回报连上最正确的信息一般! 这样分成一群群的比较好管理啦! 整个来说, Ext2 格式化后有点像下面这样
在整体的规划当中, 文件系统最前面有一个开机扇区( boot sector) , 这个开机扇区可以安装开机管理程序, 这是个非常重要的设计, 因为如此一来我们就能够将不同的开机管理程序安装到个别的文件系统最前端, 而不用覆盖整颗磁盘唯一的 MBR, 这样也才能够制作出多重开机的环境啊! 至于每一个区块群组( block group) 的六个主要内容说明如后:
- data block ( 数据区块)
data block 是用来放置文件内容数据地方, 在 Ext2 文件系统中所支持的 block 大小有 1K, 2K及 4K 三种而已。 在格式化时 block 的大小就固定了, 且每个 block 都有编号, 以方便 inode的记录啦。 不过要注意的是, 由于 block 大小的差异, 会导致该文件系统能够支持的最大磁盘容量与最大单一文件大小并不相同。 因为 block 大小而产生的 Ext2 文件系统限制如下
Block 大小 | 1KB | 2KB | 4KB |
最大单一文件限制 | 16GB | 256GB | 2TB |
最大文件系统总容量 | 2TB | 8TB | 16TB |
你需要注意的是, 虽然 Ext2 已经能够支持大于 2GB 以上的单一文件大小, 不过某些应用程序依然使用旧的限制, 也就是说, 某些程序只能够捉到小于 2GB 以下的文件而已, 这就跟文件系统无关了! 举例来说, 鸟哥在环工方面的应用中有一套秀图软件称为PAVE, 这套软件就无法捉到鸟哥在数值模式仿真后产生的大于 2GB 以上的文件! 所以后来只能找更新的软件来取代它了!
除此之外 Ext2 文件系统的 block 还有什么限制呢? 有的! 基本限制如下:
- 原则上, block 的大小与数量在格式化完就不能够再改变了( 除非重新格式化);
- 每个 block 内最多只能够放置一个文件的数据;
- 承上, 如果文件大于 block 的大小, 则一个文件会占用多个 block 数量;
- 承上, 若文件小于 block , 则该 block 的剩余容量就不能够再被使用了( 磁盘空间会浪费) 。
如上第四点所说, 由于每个 block 仅能容纳一个文件的数据而已, 因此如果你的文件都非常小, 但是你的 block 在格式化时却选用最大的 4K 时, 可能会产生一些容量的浪费喔! 我们以下面的一个简单例题来算一下空间的浪费吧!
例题: 假设你的Ext2文件系统使用 4K block , 而该文件系统中有 10000 个小文件, 每个文件大小均为 50Bytes, 请问此时你的磁盘浪费多少容量? 答: 由于 Ext2 文件系统中一个 block仅能容纳一个文件, 因此每个 block 会浪费“ 4096 - 50 = 4046 ( Byte) ”, 系统中总共有一万个小文件, 所有文件大小为: 50 ( Bytes) x 10000 = 488.3KBytes, 但此时浪费的容量为: “ 4046 ( Bytes) x 10000 = 38.6MBytes ”。 想一想, 不到 1MB 的总文件大小却浪费将近 40MB 的容量, 且文件越多将造成越多的磁盘容量浪费。
什么情况会产生上述的状况呢? 例如 BBS 网站的数据啦! 如果 BBS 上面的数据使用的是纯文本来记载每篇留言, 而留言内容如果都写上“如题”时, 想一想, 是否就会产生很多小文件了呢?
好, 既然大的 block 可能会产生较严重的磁盘容量浪费, 那么我们是否就将 block 大小订为1K 即可? 这也不妥, 因为如果 block 较小的话, 那么大型文件将会占用数量更多的 block ,而 inode 也要记录更多的 block 号码, 此时将可能导致文件系统不良的读写性能。
所以我们可以说, 在您进行文件系统的格式化之前, 请先想好该文件系统预计使用的情况。
- inode table ( inode 表格)
如前所述 inode 的内容在记录文件的属性以及该文件实际数据是放置在哪几号 block 内! 基本上, inode 记录的文件数据至少有下面这些:
- 该文件的存取模式( read/write/excute) ;
- 该文件的拥有者与群组( owner/group) ;
- 该文件的容量;
- 该文件创建或状态改变的时间( ctime) ;
- 最近一次的读取时间( atime) ;
- 最近修改的时间( mtime) ;
- 定义文件特性的旗标( flag) , 如 SetUID...;
- 该文件真正内容的指向 ( pointer) ;
inode 的数量与大小也是在格式化时就已经固定了, 除此之外 inode 还有些什么特色呢?
- 每个 inode 大小均固定为 128 Bytes ( 新的 ext4 与 xfs 可设置到 256 Bytes) ;
- 每个文件都仅会占用一个 inode 而已;
- 承上, 因此文件系统能够创建的文件数量与 inode 的数量有关;
- 系统读取文件时需要先找到 inode, 并分析 inode 所记录的权限与使用者是否符合, 若符合才能够开始实际读取 block 的内容。
我们约略来分析一下 EXT2 的 inode / block 与文件大小的关系好了。 inode 要记录的数据非常多, 但偏偏又只有 128Bytes 而已, 而 inode 记录一个 block 号码要花掉 4Byte , 假设我一个文件有 400MB 且每个 block 为 4K 时, 那么至少也要十万笔 block 号码的记录呢!inode 哪有这么多可记录的信息? 为此我们的系统很聪明的将 inode 记录 block 号码的区域定义为12个直接, 一个间接, 一个双间接与一个三间接记录区。 这是啥? 我们将 inode 的结构画一下好了。
文件系统的简单操作
稍微了解了文件系统后, 再来我们得要知道如何查询整体文件系统的总容量与每个目录所占用的容量