Linux学习之CentOS(十二)----磁盘管理之 认识ext文件系统(转)
认识ext文件系统
硬盘组成与分割
文件系统特性
Linux 的 EXT2 文件系统(inode)
与目录树的关系
EXT2/EXT3 文件的存取与日志式文件系统的功能
Linux 文件系统的运行
挂载点的意义
其他 Linux 支持的文件系统与 VFS
注1)
在整体的规划当中,文件系统最前面有一个启动扇区(boot sector),这个启动扇区可以安装启动管理程序, 这是个非常重要的设计,因为如此一来我们就能够将不同的启动管理程序安装到个别的文件系统最前端,而不用覆盖整颗硬盘唯一的 MBR, 这样也才能够制作出多重引导的环境啊!至于每一个区块群组(block group)的六个主要内容说明如后:
data block (数据区块)
data block 是用来放置文件内容数据地方,在 Ext2 文件系统中所支持的 block 大小有 1K, 2K 及 4K 三种而已。在格式化时 block 的大小就固定了,且每个 block 都有编号,以方便 inode 的记录啦。 不过要注意的是,由于 block 大小的差异,会导致该文件系统能够支持的最大磁盘容量与最大单一文件容量并不相同。 因为 block 大小而产生的 Ext2 文件系统限制如下:(注2)
注3), 这套软件就无法捉到鸟哥在数值模式仿真后产生的大于 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 号码,此时将可能导致文件系统不良的读写效能。
所以我们可以说,在您进行文件系统的格式化之前,请先想好该文件系统预计使用的情况。 以鸟哥来说,我的数值模式仿真平台随便一个文件都好几百 MB,那么 block 容量当然选择较大的!至少文件系统就不必记录太多的 block 号码,读写起来也比较方便啊!
inode table (inode 表格)
再来讨论一下 inode 这个玩意儿吧!如前所述 inode 的内容在记录文件的属性以及该文件实际数据是放置在哪几号 block 内! 基本上,inode 记录的文件数据至少有底下这些:(注4)
- 该文件的存取模式(read/write/excute);
- 该文件的拥有者与群组(owner/group);
- 该文件的容量;
- 该文件创建或状态改变的时间(ctime);
- 最近一次的读取时间(atime);
- 最近修改的时间(mtime);
- 定义文件特性的旗标(flag),如 SetUID...;
- 该文件真正内容的指向 (pointer);
inode 的数量与大小也是在格式化时就已经固定了,除此之外 inode 还有些什么特色呢?
- 每个 inode 大小均固定为 128 bytes;
- 每个文件都仅会占用一个 inode 而已;
- 承上,因此文件系统能够创建的文件数量与 inode 的数量有关;
- 系统读取文件时需要先找到 inode,并分析 inode 所记录的权限与用户是否符合,若符合才能够开始实际读取 block 的内容。
我们约略来分析一下 inode / block 与文件大小的关系好了。inode 要记录的数据非常多,但偏偏又只有 128bytes 而已, 而 inode 记录一个 block 号码要花掉 4byte ,假设我一个文件有 400MB 且每个 block 为 4K 时, 那么至少也要十万笔 block 号码的记录呢!inode 哪有这么多可记录的信息?为此我们的系统很聪明的将 inode 记录 block 号码的区域定义为12个直接,一个间接, 一个双间接与一个三间接记录区。这是啥?我们将 inode 的结构画一下好了。

图1.3.2、inode 结构示意图(注5)
上图最左边为 inode 本身 (128 bytes),里面有 12 个直接指向 block 号码的对照,这 12 笔记录就能够直接取得 block 号码啦! 至于所谓的间接就是再拿一个 block 来当作记录 block 号码的记录区,如果文件太大时, 就会使用间接的 block 来记录编号。如上图 1.3.2 当中间接只是拿一个 block 来记录额外的号码而已。 同理,如果文件持续长大,那么就会利用所谓的双间接,第一个 block 仅再指出下一个记录编号的 block 在哪里, 实际记录的在第二个 block 当中。依此类推,三间接就是利用第三层 block 来记录编号啦!
这样子 inode 能够指定多少个 block 呢?我们以较小的 1K block 来说明好了,可以指定的情况如下:
- 12 个直接指向: 12*1K=12K
由于是直接指向,所以总共可记录 12 笔记录,因此总额大小为如上所示; - 间接: 256*1K=256K
每笔 block 号码的记录会花去 4bytes,因此 1K 的大小能够记录 256 笔记录,因此一个间接可以记录的文件大小如上; - 双间接: 256*256*1K=2562K
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个号码,因此总额大小如上; - 三间接: 256*256*256*1K=2563K
第一层 block 会指定 256 个第二层,每个第二层可以指定 256 个第三层,每个第三层可以指定 256 个号码,因此总额大小如上; - 总额:将直接、间接、双间接、三间接加总,得到 12 + 256 + 256*256 + 256*256*256 (K) = 16GB
此时我们知道当文件系统将 block 格式化为 1K 大小时,能够容纳的最大文件为 16GB,比较一下文件系统限制表的结果可发现是一致的!但这个方法不能用在 2K 及 4K block 大小的计算中, 因为大于 2K 的 block 将会受到 Ext2 文件系统本身的限制,所以计算的结果会不太符合之故。
Superblock (超级区块)
Superblock 是记录整个 filesystem 相关信息的地方, 没有 Superblock ,就没有这个 filesystem 了。他记录的信息主要有:
- block 与 inode 的总量;
- 未使用与已使用的 inode / block 数量;
- block 与 inode 的大小 (block 为 1, 2, 4K,inode 为 128 bytes);
- filesystem 的挂载时间、最近一次写入数据的时间、最近一次检验磁盘 (fsck) 的时间等文件系统的相关信息;
- 一个 valid bit 数值,若此文件系统已被挂载,则 valid bit 为 0 ,若未被挂载,则 valid bit 为 1 。
Superblock 是非常重要的,因为我们这个文件系统的基本信息都写在这里,因此,如果 superblock 死掉了, 你的文件系统可能就需要花费很多时间去挽救啦!一般来说, superblock 的大小为 1024bytes。相关的 superblock 信息我们等一下会以dumpe2fs 命令来呼叫出来观察喔!
dumpe2fs 来观察的。
block bitmap (区块对照表)
如果你想要新增文件时总会用到 block 吧!那你要使用哪个 block 来记录呢?当然是选择『空的 block 』来记录新文件的数据啰。 那你怎么知道哪个 block 是空的?这就得要透过 block bitmap 的辅助了。从 block bitmap 当中可以知道哪些 block 是空的,因此我们的系统就能够很快速的找到可使用的空间来处置文件啰。
同样的,如果你删除某些文件时,那么那些文件原本占用的 block 号码就得要释放出来, 此时在 block bitmap 当中相对应到该 block 号码的标志就得要修改成为『未使用中』啰!这就是 bitmap 的功能。
inode bitmap (inode 对照表)
这个其实与 block bitmap 是类似的功能,只是 block bitmap 记录的是使用与未使用的 block 号码, 至于 inode bitmap 则是记录使用与未使用的 inode 号码啰!
了解了文件系统的概念之后,再来当然是观察这个文件系统啰!刚刚谈到的各部分数据都与 block 号码有关! 每个区段与 superblock 的信息都可以使用 dumpe2fs 这个命令来查询的!查询的方法与实际的观察如下:
[root@www ~]# dumpe2fs [-bh] 装置文件名 选项与参数: -b :列出保留为坏轨的部分(一般用不到吧!?) -h :仅列出 superblock 的数据,不会列出其他的区段内容! 范例:找出我的根目录磁盘文件名,并观察文件系统的相关信息 [root@www ~]# df <==这个命令可以叫出目前挂载的装置 Filesystem 1K-blocks Used Available Use% Mounted on /dev/hdc2 9920624 3822848 5585708 41% / <==就是这个光! /dev/hdc3 4956316 141376 4559108 4% /home /dev/hdc1 101086 11126 84741 12% /boot tmpfs 371332 0 371332 0% /dev/shm [root@www ~]# dumpe2fs /dev/hdc2 dumpe2fs 1.39 (29-May-2006) Filesystem volume name: /1 <==这个是文件系统的名称(Label) Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery sparse_super large_file Default mount options: user_xattr acl <==默认挂载的参数 Filesystem state: clean <==这个文件系统是没问题的(clean) Errors behavior: Continue Filesystem OS type: Linux Inode count: 2560864 <==inode的总数 Block count: 2560359 <==block的总数 Free blocks: 1524760 <==还有多少个 block 可用 Free inodes: 2411225 <==还有多少个 inode 可用 First block: 0 Block size: 4096 <==每个 block 的大小啦! Filesystem created: Fri Sep 5 01:49:20 2008 Last mount time: Mon Sep 22 12:09:30 2008 Last write time: Mon Sep 22 12:09:30 2008 Last checked: Fri Sep 5 01:49:20 2008 First inode: 11 Inode size: 128 <==每个 inode 的大小 Journal inode: 8 <==底下这三个与下一小节有关 Journal backup: inode blocks Journal size: 128M Group 0: (Blocks 0-32767) <==第一个 data group 内容, 包含 block 的启始/结束号码 Primary superblock at 0, Group descriptors at 1-1 <==超级区块在 0 号 block Reserved GDT blocks at 2-626 Block bitmap at 627 (+627), Inode bitmap at 628 (+628) Inode table at 629-1641 (+629) <==inode table 所在的 block 0 free blocks, 32405 free inodes, 2 directories <==所有 block 都用完了! Free blocks: Free inodes: 12-32416 <==剩余未使用的 inode 号码 Group 1: (Blocks 32768-65535) ....(底下省略).... # 由于数据量非常的庞大,因此鸟哥将一些信息省略输出了!上表与你的屏幕会有点差异。 # 前半部在秀出 supberblock 的内容,包括标头名称(Label)以及inode/block的相关信息 # 后面则是每个 block group 的个别信息了!您可以看到各区段数据所在的号码! # 也就是说,基本上所有的数据还是与 block 的号码有关就是了!很重要!
至于 block group 的内容我们单纯看 Group0 信息好了。从上表中我们可以发现:如上所示,利用 dumpe2fs 可以查询到非常多的信息,不过依内容主要可以区分为上半部是 superblock 内容, 下半部则是每个 block group 的信息了。从上面的表格中我们可以观察到这个 /dev/hdc2 规划的 block 为 4K, 第一个 block 号码为 0 号,且 block group 内的所有信息都以 block 的号码来表示的。 然后在 superblock 中还有谈到目前这个文件系统的可用 block 与 inode 数量喔!
- Group0 所占用的 block 号码由 0 到 32767 号,superblock 则在第 0 号的 block 区块内!
- 文件系统描述说明在第 1 号 block 中;
- block bitmap 与 inode bitmap 则在 627 及 628 的 block 号码上。
- 至于 inode table 分布于 629-1641 的 block 号码中!
- 由于 (1)一个 inode 占用 128 bytes ,(2)总共有 1641 - 629 + 1(629本身) = 1013 个 block 花在 inode table 上, (3)每个 block 的大小为 4096 bytes(4K)。由这些数据可以算出 inode 的数量共有 1013 * 4096 / 128 = 32416 个 inode 啦!
- 这个 Group0 目前没有可用的 block 了,但是有剩余 32405 个 inode 未被使用;
- 剩余的 inode 号码为 12 号到 32416 号。
如果你对文件系统的详细信息还有更多想要了解的话,那么请参考本章最后一小节的介绍喔! 否则文件系统看到这里对于基础认知您应该是已经相当足够啦!底下则是要探讨一下, 那么这个文件系统概念与实际的目录树应用有啥关连啊?
e2fsck 这支程序来进行的。
不过,这样的检查真的是很费时~因为要针对 metadata 区域与实际数据存放区来进行比对, 呵呵~得要搜寻整个 filesystem 呢~如果你的文件系统有 100GB 以上,而且里面的文件数量又多时, 哇!系统真忙碌~而且在对 Internet 提供服务的服务器主机上面, 这样的检查真的会造成主机复原时间的拉长~真是麻烦~这也就造成后来所谓日志式文件系统的兴起了。
日志式文件系统 (Journaling filesystem)
为了避免上述提到的文件系统不一致的情况发生,因此我们的前辈们想到一个方式, 如果在我们的 filesystem 当中规划出一个区块,该区块专门在记录写入或修订文件时的步骤, 那不就可以简化一致性检查的步骤了?也就是说:
- 预备:当系统要写入一个文件时,会先在日志记录区块中纪录某个文件准备要写入的信息;
- 实际写入:开始写入文件的权限与数据;开始升级 metadata 的数据;
- 结束:完成数据与 metadata 的升级后,在日志记录区块当中完成该文件的纪录。
在这样的程序当中,万一数据的纪录过程当中发生了问题,那么我们的系统只要去检查日志记录区块, 就可以知道哪个文件发生了问题,针对该问题来做一致性的检查即可,而不必针对整块 filesystem 去检查, 这样就可以达到快速修复 filesystem 的能力了!这就是日志式文件最基础的功能啰~
那么我们的 ext2 可达到这样的功能吗?当然可以啊! 就透过 ext3 即可! ext3 是 ext2 的升级版本,并且可向下兼容 ext2 版本呢! 所以啰,目前我们才建议大家,可以直接使用 ext3 这个 filesystem 啊! 如果你还记得 dumpe2fs 输出的信息,可以发现 superblock 里面含有底下这样的信息:
Journal inode: 8
Journal backup: inode blocks
Journal size: 128M
『为什么你想要从ext2转换到ext3呢?有四个主要的理由:可利用性、数据完整性、速度及易于转换』 『可利用性』,他指出,这意味着从系统中止到快速重新复原而不是持续的让e2fsck运行长时间的修复。ext3 的日志式条件可以避免数据毁损的可能。他也指出: 『除了写入若干数据超过一次时,ext3往往会较快于ext2,因为ext3的日志使硬盘读取头的移动能更有效的进行』 然而或许决定的因素还是在Johnson先生的第四个理由中。
『它是可以轻易的从ext2变更到ext3来获得一个强而有力的日志式文件系统而不需要重新做格式化』。『那是正确的,为了体验一下 ext3 的好处是不需要去做一种长时间的,冗长乏味的且易于产生错误的备份工作及重新格式化的动作』。
看到了吧!透过 inode 8 号记录 journal 区块的 block 指向,而且具有 128MB 的容量在处理日志呢! 这样对于所谓的日志式文件系统有没有比较有概念一点呢?^_^。如果想要知道为什么 Ext3 文件系统会更适用于目前的 Linux 系统, 我们可以参考 Red Hat 公司中,首席核心开发者 Michael K. Johnson 的话
Linux 文件系统的运行
我们现在知道了目录树与文件系统的关系了,我们也知道, 所有的数据都得要加载到内存后 CPU 才能够对该数据进行处理。想一想,如果你常常编辑一个好大的文件, 在编辑的过程中又频繁的要系统来写入到磁盘中,由于磁盘写入的速度要比内存慢很多, 因此你会常常耗在等待硬盘的写入/读取上。真没效率!
为了解决这个效率的问题,因此我们的 Linux 使用的方式是透过一个称为异步处理 (asynchronously) 的方式。所谓的异步处理是这样的:
当系统加载一个文件到内存后,如果该文件没有被更动过,则在内存区段的文件数据会被配置为干净(clean)的。 但如果内存中的文件数据被更改过了(例如你用 nano 去编辑过这个文件),此时该内存中的数据会被配置为脏的 (Dirty)。此时所有的动作都还在内存中运行,并没有写入到磁盘中! 系统会不定时的将内存中配置为『Dirty』的数据写回磁盘,以保持磁盘与内存数据的一致性。 你也可以利用 sync命令来手动强迫写入磁盘。
我们知道内存的速度要比硬盘快的多,因此如果能够将常用的文件放置到内存当中,这不就会添加系统性能吗? 没错!是有这样的想法!因此我们 Linux 系统上面文件系统与内存有非常大的关系喔:
- 系统会将常用的文件数据放置到主存储器的缓冲区,以加速文件系统的读/写;
- 承上,因此 Linux 的物理内存最后都会被用光!这是正常的情况!可加速系统效能;
- 你可以手动使用 sync 来强迫内存中配置为 Dirty 的文件回写到磁盘中;
- 若正常关机时,关机命令会主动呼叫 sync 来将内存的数据回写入磁盘内;
- 但若不正常关机(如跳电、死机或其他不明原因),由于数据尚未回写到磁盘内, 因此重新启动后可能会花很多时间在进行磁盘检验,甚至可能导致文件系统的损毁(非磁盘损毁)。
挂载点的意义 (mount point)
每个 filesystem 都有独立的 inode / block / superblock 等信息,这个文件系统要能够链接到目录树才能被我们使用。 将文件系统与目录树结合的动作我们称为『挂载』。 关于挂载的一些特性我们在稍微提过, 重点是:挂载点一定是目录,该目录为进入该文件系统的入口。 因此并不是你有任何文件系统都能使用,必须要『挂载』到目录树的某个目录后,才能够使用该文件系统的。
举例来说,如果你是依据鸟哥的方法安装你的 CentOS 5.x 的话, 那么应该会有三个挂载点才是,分别是 /, /boot, /home 三个 (鸟哥的系统上对应的装置文件名为 /dev/hdc2, /dev/hdc1, /dev/hdc3)。 那如果观察这三个目录的 inode 号码时,我们可以发现如下的情况:
[root@www ~]# ls -lid / /boot /home
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /
2 drwxr-xr-x 4 root root 1024 Sep 4 18:06 /boot
2 drwxr-xr-x 6 root root 4096 Sep 29 02:21 /home
上面的信息中由于挂载点均为 / ,因此三个文件 (/, /., /..) 均在同一个 filesystem 内,而这三个文件的 inode 号码均为 2 号,因此这三个档名都指向同一个 inode 号码,当然这三个文件的内容也就完全一模一样了! 也就是说,根目录的上一级 (/..) 就是他自己!这么说,看的懂了吗? ^_^看到了吧!
由于 filesystem 最顶层的目录之 inode 一般为 2 号,因此可以发现 /, /boot, /home 为三个不同的 filesystem 啰! (因为每一行的文件属性并不相同,且三个目录的挂载点也均不相同之故。)
我们曾经提到根目录下的 . 与 .. 是相同的东西, 因为权限是一模一样嘛!如果使用文件系统的观点来看,同一个 filesystem 的某个 inode 只会对应到一个文件内容而已(因为一个文件占用一个 inode 之故), 因此我们可以透过判断 inode 号码来确认不同文件名是否为相同的文件喔!所以可以这样看:
[root@www ~]# ls -ild / /. /..
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /.
2 drwxr-xr-x 23 root root 4096 Sep 22 12:09 /..
其他 Linux 支持的文件系统与 VFS
虽然 Linux 的标准文件系统是 ext2 ,且还有添加了日志功能的 ext3 ,事实上,Linux 还有支持很多文件系统格式的, 尤其是最近这几年推出了好几种速度很快的日志式文件系统,包括 SGI 的 XFS 文件系统, 可以适用更小型文件的 Reiserfs 文件系统,以及 Windows 的 FAT 文件系统等等, 都能够被 Linux 所支持喔!常见的支持文件系统有:
- 传统文件系统:ext2 / minix / MS-DOS / FAT (用 vfat 模块) / iso9660 (光盘)等等;
- 日志式文件系统: ext3 / ReiserFS / Windows' NTFS / IBM's JFS / SGI's XFS
- 网络文件系统: NFS / SMBFS
想要知道你的 Linux 支持的文件系统有哪些,可以察看底下这个目录:
[root@www ~]# ls -l /lib/modules/$(uname -r)/kernel/fs
Linux VFS (Virtual Filesystem Switch)系统目前已加载到内存中支持的文件系统则有:
[root@www ~]# cat /proc/filesystems
了解了我们使用的文件系统之后,再来则是要提到,那么 Linux 的核心又是如何管理这些认识的文件系统呢? 其实,整个 Linux 的系统都是透过一个名为 Virtual Filesystem Switch 的核心功能去读取 filesystem 的。 也就是说,整个 Linux 认识的 filesystem 其实都是 VFS 在进行管理,我们使用者并不需要知道每个 partition 上头的 filesystem 是什么~ VFS 会主动的帮我们做好读取的动作呢~
假设你的 / 使用的是 /dev/hda1 ,用 ext3 ,而 /home 使用 /dev/hda2 ,用 reiserfs , 那么你取用 /home/dmtsai/.bashrc 时,有特别指定要用的什么文件系统的模块来读取吗? 应该是没有吧!这个就是 VFS 的功能啦!透过这个 VFS 的功能来管理所有的 filesystem, 省去我们需要自行配置读取文件系统的定义啊~方便很多!整个 VFS 可以约略用下图来说明:

图 1.8.1、VFS 文件系统的示意图
『它是可以轻易的从ext2变更到ext3来获得一个强而有力的日志式文件系统而不需要重新做格式化』。『那是正确的,为了体验一下 ext3 的好处是不需要去做一种长时间的,冗长乏味的且易于产生错误的备份工作及重新格式化的动作』。

图 1.8.1、VFS 文件系统的示意图