本文为原创文章,转载注明出处,欢迎关注网站https://hkvision.cn

缘起

接上面的文件系统介绍,接着介绍一下Ext4文件系统

Ext4的历史

知乎上有一篇文章,Ext4的历史讲的较为详细,可以直接参考,这里只简单讲一下。

Ext4由Ext2,Ext3发展而来,从结构上是兼容Ext2/3的,也就是说你可以在不损失数据的情况下,直接平滑过渡到Ext4文件系统,这一点上Ext4是占有极大的优势的(与XFS等其他文件系统相比)。

对于Linux,Ext系列的文件系统就像亲儿子一样,可以说Ext系列文件系统的发展就是伴随着Linux发展的,因此实际上Ext系列的文件系统和VFS即为相像,甚至于部分结构是嵌在Linux中的而不是Ext中。

Ext4的一些特性

和Ext3相比,Ext4有一些很有意思的特性

  • 向后兼容性:Ext4被设计的与Ext3之间相互兼容。

  • 大文件系统:ext3 文件系统使用 32 位寻址,这限制它仅支持 2 TiB 文件大小和 16 TiB 文件系统系统大小(这是假设在块大小为 4 KiB 的情况下,一些 ext3 文件系统使用更小的块大小,因此对其进一步被限制)。

    ext4 使用 48 位的内部寻址(理论上可以到64位,只是限制了,作者认为Ext4只会是一个过渡方案),理论上可以在文件系统上分配高达 16 TiB 大小的文件,其中文件系统大小最高可达 1000000 TiB(1 EiB)。在早期 ext4 的实现中有些用户空间的程序仍然将其限制为最大大小为 16 TiB 的文件系统,但截至 2011 年,e2fsprogs 已经直接支持大于 16 TiB 大小的 ext4 文件系统。例如,红帽企业 Linux 在其合同上仅支持最高 50 TiB 的 ext4 文件系统,并建议 ext4 卷不超过 100 TiB。

  • extent:*区段(extent)*是一系列连续的物理块 (最多达 128 MiB,假设块大小为 4 KiB),可以一次性保留和寻址。使用区段可以减少给定文件所需的 inode 数量,并显著减少碎片并提高写入大文件时的性能。简单来说,extent就是将Ext3中的使用多级索引寻址转变成了给定块开头和结尾的位置这种寻址方式。

  • 多块分配:ext3 为每一个新分配的块调用一次块分配器。当多个写入同时打开分配器时,很容易导致严重的碎片。然而,ext4 使用延迟分配,这允许它合并写入并更好地决定如何为尚未提交的写入分配块。

  • 持久的预分配:在为文件预分配磁盘空间时,大部分文件系统必须在创建时将零写入该文件的块中。ext4 允许替代使用 fallocate(),它保证了空间的可用性(并试图为它找到连续的空间),而不需要先写入它。这显著提高了写入和将来读取流和数据库应用程序的写入数据的性能。

  • 延迟分配:准确来说,延迟分配是一个很棒的功能,因为这会使得块分配器能够在获得了更多信息的时候再进行分配决策,而不是拿到一个待写块就迫不及待的给这个块分配物理块,这样能极大的减少文件的碎片化,也能更好的利用空间,提高性能。

    但是同样的,这个功能也会带来一个很严重的问题,那就是在发生异常掉电的时候,原来的方式,即使掉电了,也能保证在掉电前保存的数据被正确的保存下来,但是延迟分配会使得当文件即使被关闭之后,待写的数据可能仍然呆在缓存当中没有被写,此时发生掉电则会出现一个令人困惑的结果,明明文件已经成功关闭了,但是掉电后文件依然不存在,对于写上层应用的程序员来说,这简直就是一个BUG!

    一个较好的解决方案是,在真正需要让数据落盘的时候,调用fsync()函数,这个函数会让次文件描述符在写缓存中的数据真实写到磁盘中,另外一种方案是,在打开文件时,选择O_SYNC模式,这样在对以这种模式打开的文件描述符进行写的时候,先将数据写在缓存中,然后立即让块分配器为这些数据分配物理块并写入到磁盘上。

  • 增多的子目录(最多无限):ext3 仅限于 32000 个子目录;ext4 允许无限数量的子目录。从 2.6.23 内核版本开始,ext4 使用 HTree 索引来减少大量子目录的性能损失。

  • 日志检验:ext3 没有对日志进行校验,这给处于内核直接控制之外的磁盘或自带缓存的控制器设备带来了问题。如果控制器或具自带缓存的磁盘脱离了写入顺序,则可能会破坏 ext3 的日记事务顺序,从而可能破坏在崩溃期间(或之前一段时间)写入的文件。理论上,这个问题可以使用写入 障碍(barrier) —— 在安装文件系统时,你在挂载选项设置 barrier=1,然后设备就会忠实地执行 fsync 一直向下到底层硬件。通过实践,可以发现存储设备和控制器经常不遵守写入障碍 —— 提高性能(和跟竞争对手比较的性能基准),但增加了本应该防止数据损坏的可能性。对日志进行校验和允许文件系统崩溃后第一次挂载时意识到其某些条目是无效或无序的。因此,这避免了回滚部分条目或无序日志条目的错误,并进一步损坏的文件系统 —— 即使部分存储设备假做或不遵守写入障碍。

  • 快速文件检查:在 ext3 下,在 fsck 被调用时会检查整个文件系统 —— 包括已删除或空文件。相比之下,ext4 标记了 inode 表未分配的块和扇区,从而允许 fsck 完全跳过它们。这大大减少了在大多数文件系统上运行 fsck 的时间,它实现于内核 2.6.24。

  • 改进的时间戳:ext3 提供粒度为一秒的时间戳。虽然足以满足大多数用途,但任务关键型应用程序经常需要更严格的时间控制。ext4 通过提供纳秒级的时间戳,使其可用于那些企业、科学以及任务关键型的应用程序。ext3 文件系统也没有提供足够的位来存储 2038 年 1 月 18 日以后的日期。ext4 在这里增加了两个位,将 Unix 纪元扩展了 408 年。如果你在公元 2446 年读到这篇文章,你很有可能已经转移到一个更好的文件系统 —— 如果你还在测量自 1970 年 1 月 1 日 00:00(UTC)以来的时间,这会让我死后得以安眠。

  • 在线碎片整理:ext2 和 ext3 都不直接支持在线碎片整理 —— 即在挂载时会对文件系统进行碎片整理。ext2 有一个包含的实用程序 e2defrag,它的名字暗示 —— 它需要在文件系统未挂载时脱机运行。(显然,这对于根文件系统来说非常有问题。)在 ext3 中的情况甚至更糟糕 —— 虽然 ext3 比 ext2 更不容易受到严重碎片的影响,但 ext3 文件系统运行 e2defrag 可能会导致灾难性损坏和数据丢失。尽管 ext3 最初被认为“不受碎片影响”,但对同一文件(例如 BitTorrent)采用大规模并行写入过程的过程清楚地表明情况并非完全如此。一些用户空间的手段和解决方法,例如 Shake,以这样或那样方式解决了这个问题 —— 但它们比真正的、文件系统感知的、内核级碎片整理过程更慢并且在各方面都不太令人满意。ext4 通过 e4defrag 解决了这个问题,且是一个在线、内核模式、文件系统感知、块和区段级别的碎片整理实用程序。

  • 元数据校验和:ext4为整个文件系统中几乎所有的元数据都提供了校验和的功能,例如超级块,组描述符,目录项等。

  • 大分配块:大分配块就是让最小的分配块成为多个块,例如8K等,但实际上我并没有弄明白这个功能和直接将块大小设置为8K有什么区别。

Ext4的一些局限性

尽管看起来Ext4很不错,但是随着计算机技术的发展,现实给文件系统技术提出了新的要求,例如超大数据量。

是的,尽管Ext4理论上支持1EB的文件系统大小,但是实际使用的时候,你不应该让Ext4整个文件系统使用超过50TB,最多不能超过100TB

另外,尽管Ext4使用了日志的方式保证了掉电时的文件系统一致性,但是对于数据的破坏远不止掉电这一个因素,比如比特翻转(宇宙射线的影响),或者仅仅是随着时间的推移,磁性衰减了,这些情况Ext4都无法检测或者进行纠错。至少Ext4文件系统不可能作为卫星或者火箭的控制系统的文件系统。

因此,Ext4仅仅是一个纯的文件系统,而不是一个存储卷管理器(现代化的文件系统总会带有这个功能)。