Ext 2 文件系统
Ext 2 物理结构
Ext2 第二代扩展文件系统(second extended filesystem,缩写为 ext2),是 LINUX 内核所用的文件系统。
Ext2文件系统特性:
1、磁盘块分为组;
2、支持快速符号链接:如果链接目标的路径足够短,则将其存储在inode自身中;
3、在启动时支持对文件系统的状态进行自动的一致性检查;
4、Ext2 的索引节点中引入新的字段(块片、删除逻辑、日志)。
与现代文件系统相比,Ext2文件系统的代码非常紧凑;
必须建立各种结构 (在内核中定义为C语言数据类型),来存放文件系统的数据 ,包括文件内容、目录层次结构的表示、相关的管理数据(如访问权限或与用户和组的关联),以及用于管理文件系统内部信息的元数据。
这些对从块设备读取数据进行分析而言,都是必要的。这些结构的持久副本显然需要存储在硬盘上,这样数据在两次会话之间不会丢失。下一次启动重新激活内核时,数据仍然是可用的。因为硬盘和物理内存的需求不同,同一数据结构通常会有两个版本。一个用于在磁盘上的持久存储,另一个用于在内存中的处理。
Ext2文件系统是一种基于块的文件系统,它将硬盘划分为若干块,每个块的长度都相同,按块管理元数据和文件内容;
块组是 Ext2 文件系统的核心要素。块组是该文件系统的基本成分,容纳了文件系统的其他结构。
为什么Ext2文件系统允许这样浪费空间?有两个原因,可以证明提供额外空间的做法是正确的:
(1)如果系统崩溃破坏了超级块,有关文件系统结构和内容的所有信息都会丢失。如果有冗余的副本,该信息是可能恢复的(难度极高,大多数用户可能一点也恢复不了)。
(2)通过使文件和管理数据尽可能接近,减少了磁头寻道和旋转,这可以提高文件系统的性能。
Ext 2 数据结构
1.超级块
超级块是文件系统的核心结构,保存了文件系统所有的特征数据 。内核在装载文件系统时,最先 看到的就是超级块的内容。内核只使用第一个块组 的超级块读取文件系统的元信息。使用 ext2_super_block
结构定义超级:
s_magic
字段存储一个魔数,该数值确认装载的文件系统确实是 Ext 2 类型,s_minor_rev_level
用于区分文件系统的不同的版本。
2.组描述符
每个块组都一个组描述符的集合,紧随超级块之后。其中保存的信息反映了文件系统每个块组的内容 ,因此不仅关系到当前块组的数据块,还与其他块组的 数据块 和 inode块 相关。用于定义单个组描述符的数据结构比超级块结构短得多:
3.inode
每个块组都包含一个inode位图 和一个本地的inode表 , inode表可能延续到几个块。位图的内容与本地块组相关,不会复制到文件系统中任何其他位置。inode 位图用于概述块组中已用和空闲的 inode 。
4.目录和文件
文件系统的拓朴结构,在经典的 UNIX 文件系统中,目录不过是一种特殊的文件,其中是inode 指针和对应的文件名列表,表示了当前目录下的文件和子目录。
对于Ext2文件系统,也是这样。每个目录表示为一个inode,会对其分配数据块。数据块中包含了用于描述目录项的结构。
Ext 2 文件系统操作
虚拟文件系统和具体实现之间的关联大体上由3个结构建立,结构中包含了一系列的函数指针。所有的文件系统都必须实现该关联。
(1)用于操作文件内容的操作保存在file_operations
中。
(2)用于此类文件对象自身的操作保存在inode_operations
中。
(3)用于一般地址空间的操作保存在address_space_operations
中。
Ext 2 文件系统对不同的文件类型提供了不同的file_operations
实例。很自然,最常用的变体是用于普通文件:
目录也有自身的file_operations
实例:
目录有更多可用的inode
操作:
文件系统和块层通过address_space_operations
关联。在 Ext 2 文件系统中,这些源码操作初始化如下:
此结构( super_operations
)用于与超级块交互(读、写、分配inode)。对于 Ext 2 文件系统的,具体源码初始化如下:
Ext 4 文件系统
使用 Ext 3 文件系统的 Linux 内核中实现三个级别的日志记录:日记 journal、顺序 ordered 和回写 writeback。
案例:Ext 3 文件系统,数据块分配器每次分配一个 4 kb 的块,如果我们要写一个100mb文件就需要调用 25600 次数据块分配器。
Ext 4 文件系统被分成一系列块组,为减少磁盘碎片产生的性能瓶颈,块分配器尽量保持每个文件的数据块都在同个块组中,从而减少寻道时间。以 4kb 数据块为准,一个块组可以包含 32768 个数据块,也就是 128 mb。
Ext 4 文件系统特性
EXT 4 是第四代扩展文件系统(Fourth extended filesystem,缩写为 ext4)是 Linux 系统下的日志文件系统,是 ext 3 文件系统的后继版本。内核2.6.28引入 Ext 4 文件系统成为稳定版。
当格式化磁盘成为 Ext4 文件系统时,mkfs 将在块组描述表后面分配预留 GDT 表数据块(主要作用用于将扩展文件系统)
GDT 表(Global Descriptor Table) 是 x86 架构中用于实现分段机制的数据结构之一。它是在保护模式下用于管理内存分段的重要组成部分。GDT 表定义了一组段描述符,每个段描述符描述了一个内存段的属性和位置。
更大的文件系统和更大的文件;更多的子目录数量;更多的块和i-节点数量;多块分配;
持久性预分配;延迟分配;盘区结构;日志校验功能;支持"无日志"模式;在线碎片整理;
支持快速fsck;支持纳秒级时间戳。
Ext 4 文件系统数据结构
1.超级块
专门用于描述文件系统的全部配置信息:比如 inode数量、数据块个数、管理信息等。
2.块组描述符(GDT)
块组描叙符用于保存元组的信息,其占用一个或者多个数据块,具体取决于文件系统的大小,它主要包含块位图,inode 位图和 inode 表位置等 。
数据块位图:用于描述该块组所管理的块的分配状态 。
inode 位图:用于描述该块组所管理的 inode 分配状态。
3.节点表(Inode Table)
inode 存储了 inode 号、文件属性元数据、指向文件占用的 block 的指针,每一个 inode 占用 128 字节或 256 字节。
4.Extent 树
Ext4 中用 extent 树代替逻辑块映射 。用一个struct ext4_extent
结构就可以映射多个数据块,减少元数据块的使用。
struct ext4_extent_idx
:extent
树的内部节点,也称为索引节点。
Ext 4 日志 JBD2
Ext4日志,在文件系统中是一个文件,默认Inode号为8,大小为一个块组(128MiB),日志文件通常存储在文件系统分区的中部。
文件系统在磁盘上保留一段小的连续区域(默认128MB),作为尽可能需要快速写入磁盘的"重要"数据的存放地。
一旦该重要数据事务完全写到磁盘,将其从磁盘写缓存中刷出。被提交的数据一份记录也被写到日志。Ext4和Ocfs2都用JBD2。
Ext 4 支持三种日志模式
(1)ordered
,日志中只记录元数据,数据写入磁盘后才会提交日志。这是默认模式。
(2)journal
,日志中同时记录元数据及数据内容,最安全也是最慢的模式,同时会导致延迟分配及Direct-I/O失效。
(3)writeback
,日志中只记录元数据,但是不保证元数据和数据的写入顺序。(言外之意:元数据提交了,数据可能还没有落盘)。
数据块头部结构 :日志中的每个数据块的开头都是一个12bytes
的数据结构,struct journal_header_s
超级块 :日志的超级块比Ext4的超级块简单。保存在日志的超级块中是日志的关键数据。日志超级块使用数据结构struct journal_superblock_s
表示,大小为1024 bytes
描述数据块 :它包含一个日志数据块 tags
的数组,这些 tags
描述日志中接下来的数据块的最终位置。
撤消块 :用于记录本事务中的数据块链表,取代任何潜在日志中的更陈旧的数据块,这样可以加速恢复,因为陈旧的数据块不必要写到磁盘。
提交块 :提交块表明了一个事务已完整写到日志.
事务最核心属性就是状态,当事务正在提交,它的生命周期经过如下阶段:running-->locked-->flush-->commit-->ok
kjournald 线程 与每个进行日志的设备关联,此线程保证运行中的事务会在一个特定间隔后被提交。事务提交分成阶段操作(日志的逻辑结构):
恢复(journal recover) :
发现日志记录的尾部-->为日志记录准备一串被撤消的块-->未被撤消的块以确保磁盘一致性的顺序被重新写入(重放操作)