大多数现代Linux发行版都默认使用ext4文件系统,就像以前的Linux发行版默认使用ext3,ext2和ext(如果您回过头来看)一样。
如果您是Linux或文件系统的新手,您可能想知道ext4带来了ext3没有带来的好处。 您可能还想知道,鉴于诸如btrfs,xfs和zfs之类的备用文件系统的新闻报道越来越多,ext4是否仍在积极开发中。
在准备本概述时,我大量参考了Wikipedia的各种ext文件系统文章,关于ext4的kernel.org Wiki条目以及我自己的经验。
ext的简要历史
MINIX文件系统
在没有ext之前,已经有了MINIX文件系统。 如果您不了解Linux的历史,那么MINIX是一个非常小的Unix操作系统,适用于IBM PC / AT微型计算机。 Andrew Tannenbaum出于教学目的开发了它,并于1987年发布了源代码(印刷形式!)。
![IBM PC AT IBM PC AT](https://i-blog.csdnimg.cn/blog_migrate/4c306dc40eccdc99de41a8224ad00491.jpeg)
IBM的1980年代中期PC / AT, MBlairMartin , CC BY-SA 4.0
尽管您可以仔细阅读MINIX的源代码,但它实际上并不是免费的开源软件(FOSS)。 Tannebaum的书的出版商要求经营MINIX的许可费为69美元,这已包括在该书的费用中。 尽管如此,这在当时还是非常便宜的,并且MINIX的采用Swift发展起来,很快就超出了Tannenbaum最初使用它来简单地指导操作系统编码的初衷。 在整个1990年代,您会发现MINIX的安装在世界各地的大学中蓬勃发展;年轻的Linus Torvalds使用MINIX来开发原始的Linux内核,该内核最初于1991年发布,并在GPL下于1992年12月发布。
但是,等等,这是一篇关于文件系统的文章,对不对? 是的,MINIX有自己的文件系统,Linux的早期版本也依赖该文件系统。 像MINIX一样,它可以被形容为同类的“玩具”示例-MINIX文件系统只能处理最多14个字符的文件名,并且只能处理64MB的存储空间。 1991年,典型的硬盘驱动器大小已达到40-140MB。 Linux显然需要更好的文件系统!
分机
当Linus入侵刚起步的Linux内核时,RémyCard致力于第一个ext文件系统。 ext解决了MINIX文件系统中最严重的问题,于1992年首次实现-仅在Linux本身首次发布之后一年!
1992年的ext在Linux内核中使用了新的虚拟文件系统(VFS)抽象层。 与之前的MINIX文件系统不同,ext可以寻址多达2GB的存储空间并处理255个字符的文件名。
但是ext的统治时间不长,主要是因为它具有原始时间戳记(每个文件只有一个时间戳,而不是我们今天熟悉的用于inode创建,文件访问和文件修改的三个独立标记)。 仅仅一年后,ext2吃了午餐。
ext2
Rémy很清楚地很快意识到了ext的局限性,因为他在一年后设计了ext2作为其替代产品。 尽管ext仍然起源于“玩具”操作系统,但ext2从一开始就被设计为商业级文件系统,其原理与BSD的Berkeley快速文件系统相同。
Ext2提供最大的文件大小(以千兆字节为单位)和文件系统大小(以TB为单位),在1990年代大行其道。 它在Linux内核中以及最终在MINIX中以及被使其可用于MacOS和Windows的第三方模块中Swift并被广泛采用。
但是,仍然有许多问题需要解决:像1990年代的大多数文件系统一样,如果在将数据写入磁盘时系统崩溃或断电,ext2文件系统很容易遭受灾难性破坏。 随着时间的流逝,由于碎片(将单个文件存储在多个位置,物理上分散在旋转磁盘上),它们也遭受严重的性能损失。
尽管存在这些问题,但ext2仍在当今一些孤立的情况下使用-最常见的是作为便携式USB拇指驱动器的格式。
ext3
在ext2被采用的六年后的1998年,Stephen Tweedie宣布他正在努力对其进行重大改进。 它成为ext3,并于2001年11月被内核版本为2.4.15的主线Linux所采用。
Ext2在大多数Linux发行版中都做得很好,但是-像FAT,FAT32,HFS和当时的其他文件系统一样,它在断电期间很容易遭受灾难性破坏。 如果在将数据写入文件系统时断电,则可以将其保持在所谓的不一致状态中,即其中的事情被半完成和半撤消。 这可能会导致大量文件的丢失或损坏,这些文件与正在保存的文件无关,甚至无法卸载整个文件系统。
Ext3和其他1990年代后期的文件系统(例如Microsoft的NTFS)使用日记来解决此问题。 日志是磁盘上的一种特殊分配,其中写入存储在事务中。 如果事务完成写入磁盘,则日记中的数据将提交给文件系统本身。 如果在执行该操作之前系统崩溃 ,则新重启的系统会将其识别为未完成的事务,并将其回滚,就好像从未发生过一样。 这意味着正在处理的文件可能仍然会丢失,但是文件系统本身保持一致,并且所有其他数据都是安全的。 ext3的Linux内核实现中提供了三种日志记录级别: journal , ordered和writeback 。
- 日志是最低风险的模式,在将数据和元数据提交到文件系统之前,将数据和元数据都写入日志。 这样可以确保所写文件以及整个文件系统的一致性,但是会大大降低性能。
- 在大多数Linux发行版中, 订购是默认模式。 有序模式将元数据写入日志,但将数据直接提交至文件系统。 顾名思义,这里的操作顺序是严格的:首先,将元数据提交给日志;然后,将元数据提交给日志。 其次,将数据写入文件系统,然后日志中的关联元数据才刷新到文件系统本身。 这样可以确保在发生崩溃的情况下,与未完成写入相关联的元数据仍保留在日志中,并且文件系统可以在回滚日志的同时清理那些未完成的写入。 在有序模式下,崩溃可能会导致文件崩溃或在崩溃期间被主动写入的文件损坏,但是可以保证文件系统本身以及未被主动写入的文件是安全的。
- 写回是第三种也是最不安全的日记模式。 在写回模式下(如有序模式),将记录元数据,但不记录数据。 与有序模式不同,元数据和数据都可以以最佳性能有意义的任何顺序进行写入。 这可以显着提高性能,但安全性要差得多。 尽管写回模式仍然可以保证文件系统本身的安全,但是在崩溃期间或崩溃之前写入的文件很容易丢失或损坏。
像之前的ext2一样,ext3使用16位内部寻址。 这意味着块大小为4K时,它可以处理的最大文件大小为2 TiB,最大文件系统大小为16 TiB。
ext4
Theodore Ts'o(当时是ext3的主要开发人员)在2006年宣布ext4,并于两年后以内核版本2.6.28将其添加到主线Linux中。 Ts'o将ext4描述为权宜之计,它极大地扩展了ext3,但仍然依赖于旧技术。 他希望它最终会被真正的下一代文件系统所取代。
![Dell Precision 380工作站 Dell Precision 380 workstation](https://i-blog.csdnimg.cn/blog_migrate/6ffe23efe0d289abdc4c8b8dc14df25f.jpeg)
Dell Precision 380工作站, Lance Fisher , CC BY-SA 2.0
Ext4在功能上与ext3非常相似,但是带来了大文件系统支持,更高的抗碎片性,更高的性能以及更佳的时间戳。
Ext4与ext3
Ext3和ext4有一些非常具体的区别,我将在这里重点介绍。
向后兼容
Ext4专门设计为与ext3尽可能向后兼容。 这不仅允许将ext3文件系统就地升级到ext4; 它还允许ext4驱动程序以ext3模式自动挂载ext3文件系统,从而不必分别维护两个代码库。
大文件系统
Ext3文件系统使用32位寻址,将它们限制为2个TiB文件和16个TiB文件系统(假定4 KiB块大小;某些ext3文件系统使用较小的块大小,因此受到进一步限制)。
Ext4使用48位内部寻址,从理论上讲,可以在不超过1,000,000 TiB(1 EiB)的文件系统上分配不超过16 TiB的文件。 某些userland实用程序仍将ext4的早期实现限制为16个TiB文件系统,但从2011年开始,e2fsprogs已直接支持创建> 16TiB ext4文件系统。 举一个例子,红帽企业Linux按照合同规定最多支持50 TiB的ext4文件系统,并建议ext4卷不超过100 TiB。
分配改进
Ext4在将存储块写入磁盘之前对存储块分配方式进行了许多改进,这可以显着提高读取和写入性能。
范围
范围是可以立即保留和寻址的一系列连续物理块(假设4 KiB块大小,最多可达128 MiB)。 利用范围可减少给定文件所需的索引节点数量,并显着减少碎片并提高写入大型文件时的性能。
多块分配
Ext3为分配的每个新块调用一次其块分配器。 同时打开多个写入器时,这很容易导致严重的碎片。 但是,ext4使用延迟分配,这使它可以合并写入并就如何为尚未提交的写入分配块做出更好的决策。
持续预分配
在为文件预分配磁盘空间时,大多数文件系统在创建时必须向该文件的块写入零。 Ext4允许使用fallocate()
代替,这保证了空间的可用性(并尝试为其找到连续的空间),而无需首先对其进行写入。 这显着提高了针对流和数据库应用程序的写入数据的写入和将来读取的性能。
延迟分配
这是一种耐嚼且有争议的功能。 延迟分配使ext4可以等待分配将要写入数据的实际块,直到准备将数据提交到磁盘为止。 (相反,即使数据仍在流入写缓存时,ext3也会立即分配块。)
随着数据在缓存中累积而延迟分配块,文件系统可以对如何分配这些块做出更明智的选择,从而减少碎片(写入和随后读取)并显着提高性能。 不幸的是,当程序员想要确保数据已完全刷新到磁盘上时,它增加了未专门编写来调用fsync()
的程序中数据丢失的可能性。
假设某个程序完全重写了一个文件:
fd=open("file" ,O_TRUNC); write(fd, data); close(fd);
对于旧文件系统, close(fd);
足以保证file
内容将刷新到磁盘。 即使严格地说,写操作不是事务性的,但是如果在关闭文件后发生崩溃,丢失数据的风险很小。
如果写入不成功(由于程序错误,磁盘错误,断电等),则文件的原始版本和更新版本都可能丢失或损坏。 如果其他进程正在写入文件时访问该文件,则它们将看到损坏的版本。 而且,如果其他进程打开了文件并且不希望其内容发生更改(例如,将共享库映射到多个正在运行的程序中),则它们可能会崩溃。
为了避免这些问题,某些程序员完全避免使用O_TRUNC
。 相反,他们可能会写入一个新文件,将其关闭,然后在旧文件上重命名该文件:
fd=open("newfile"); write(fd, data); close(fd); rename("newfile", "file");
在没有延迟分配的文件系统下 ,这足以避免上面概述的潜在损坏和崩溃问题:由于rename()
是原子操作,因此不会因崩溃而中断; 只要有打开的文件句柄,正在运行的程序将继续引用旧的,现在未链接的file
版本。 但是由于ext4的延迟分配可能导致写入延迟和重新排序,因此可以在将newfile
的内容实际写入磁盘之前执行rename("newfile","file")
,这带来了并行进程获取的问题。错误版本的file
再次出现。
为了缓解这种情况,Linux内核(自2.6.30版本开始)尝试检测这些常见的代码情况,并强制立即分配有问题的文件。 这样可以减少但不能防止数据丢失的可能性,并且对新文件完全没有帮助。 如果您是开发人员,请注意:确保立即将数据写入磁盘的唯一方法是适当地调用fsync()
。
无限子目录
Ext3限于总共32,000个子目录; ext4允许无限数量。 从内核2.6.23开始,ext4使用HTree索引来减轻大量子目录的性能损失。
日记校验
Ext3不会校验其日志,这会给磁盘或控制器设备带来问题,这些磁盘或控制器设备具有自己的缓存,但不受内核直接控制。 如果控制器或具有自己的高速缓存的磁盘的写入顺序不正确,则可能会破坏ext3的日记记录事务顺序,从而可能在崩溃期间(或崩溃之前)破坏正在写入的文件。
从理论上讲,此问题可以通过使用写屏障来解决-挂载文件系统时,您可以在挂载选项中设置barrier=1
,然后设备将完全fsync()
调用直至金属。 在实践中,已经发现存储设备和控制器通常不遵守写入障碍,从而提高了性能(以及与竞争对手相比的基准),但增加了应避免的数据损坏的可能性。
对日志进行校验和检查可以使文件系统意识到崩溃后第一次装入时其某些条目无效或乱序。 因此,这避免了回滚部分或无序日记帐分录并进一步损坏文件系统的错误-即使存储设备在说谎并且不遵守障碍。
快速文件系统检查
在ext3下,需要在调用fsck
时检查整个文件系统(包括已删除和空文件)。 相比之下,ext4则将未分配的块和索引节点表标记为此类,从而使fsck
完全跳过它们。 从内核2.6.24开始,这大大减少了在大多数文件系统上运行fsck
的时间。
改进时间戳
Ext3提供了精确到一秒的时间戳。 关键任务应用程序虽然可以满足大多数用途的需求,但它们经常需要更严格的时间控制。 Ext4通过提供纳秒级的时间戳,使其可用于那些企业,科学和关键任务应用程序。
Ext3文件系统也没有提供足够的位来存储2038年1月18日以后的日期。Ext4在此处添加了另外的两位,从而将Unix时代又延长了 408年。 如果您是在2446 AD上阅读此书,则希望您已经转移到一个更好的文件系统上,但是如果您仍在测量自1970年1月1日UTC 00:00起的时间,那会让我死后非常非常高兴。
在线碎片整理
ext2和ext3都不直接支持联机碎片整理,即在挂载时对文件系统进行碎片整理。 Ext2有一个包含的实用程序e2defrag ,顾名思义,但它没有安装文件系统时需要脱机运行。 (显然,这对于根文件系统来说尤其成问题。)ext3中的情况甚至更糟—尽管与ext2相比,ext3遭受严重碎片的可能性要小得多,对ext3文件系统运行e2defrag可能会导致灾难性的损坏和数据失利。
尽管最初将ext3视为“不受碎片影响的”,但对同一文件采用大规模并行写入过程的进程(例如BitTorrent)清楚地表明情况并非完全如此。 一些用户空间的黑客和变通办法(例如Shake)以一种或另一种方式解决了这一问题,但是它们比真正的文件系统感知的内核级碎片整理过程更慢,并且以各种方式不令人满意。
Ext4通过e4defrag解决了这个问题, e4defrag是一种在线的,内核模式的,文件系统感知的,块级扩展级别的碎片整理实用程序。
正在进行的ext4开发
正如Monty Python瘟疫的受害者曾经说过的那样,Ext4是“还没死!” 尽管它的主要开发人员将其视为实现真正的下一代文件系统的唯一权宜之计,但由于技术或许可问题,可能的候选方案都还没有准备好在一段时间内部署为根文件系统。
ext4的未来版本中仍然开发了一些关键功能,包括元数据校验和,一流的配额支持和大型分配块。
元数据校验和
由于ext4具有冗余超级块,因此对其中的元数据进行校验和可为文件系统提供一种自行确定主要超级块是否已损坏并需要使用备用块的方法。 可以从损坏的超级块中恢复而无需校验和-但用户首先需要意识到它已损坏,然后尝试使用替代方法手动挂载文件系统。 在某些情况下,由于以损坏的主超级块装载文件系统读写可能导致进一步的损坏,因此即使有足够的经验的用户,这也不是一个充分的解决方案!
与下一代文件系统(例如btrfs或zfs)提供的极其强大的按块校验和相比,ext4的元数据校验和是一个相当弱的功能。 但这总比没有好。
尽管这听起来很容易,是的,校验和是万能的,但是事后将校验和连接到文件系统中仍然存在一些重大挑战。 有关详细信息,请参见设计文档 。
一流的配额支持
等等,配额?! 自ext2天以来,我们就拥有这些! 是的,但是他们一直都是事后的想法,而且他们总是很烂。 可能不值得在这里详细介绍这些繁琐的细节,但是设计文档列出了将配额从用户空间转移到内核并更正确和高效地实施的方式。
大型分配块
随着时间的流逝,那些讨厌的存储系统会越来越大。 随着一些已经使用8K硬件块大小的固态驱动器,ext4对4K块的当前限制越来越受到限制。 较大的存储块可以减少碎片并显着提高性能,但代价是增加了“松弛”空间(当您仅需要块的一部分来存储文件或文件的最后一块时,剩余的空间)。
您可以在设计文档中查看详细信息。
ext4的实际限制
Ext4是一个健壮,稳定的文件系统,大多数人都应该在2018年将它用作根文件系统。但是它不能处理所有事情。 让我们简短地谈谈您现在或将来可能对ext4 不应期望的一些事情。
虽然EXT4可以处理高达1 EIB相当于1,000,000 TiB系的数据,你真的, 真的不应该试图这样做。 除了仅能记住更多块的地址之外,还有一些规模问题,而ext4现在(而且可能永远不会)很好地扩展到50-100 TiB以上的数据。
Ext4还不足以保证数据的完整性。 与ext3天内的日志记录一样,虽然有了很大的进步,但它并没有涵盖很多导致数据损坏的常见原因。 如果数据已经在磁盘上而已损坏 (由于硬件故障,宇宙射线的影响(是的,实际上),或者数据随时间推移而简单退化),则ext4无法检测或修复这种损坏。
ext4建立在最后两项之上,只是一个纯文件系统 ,而不是存储卷管理器。 这意味着,即使您有多个磁盘,因此也可以从理论上从中恢复奇偶校验或冗余磁盘,ext4也无法知道或利用它来谋取利益。 从理论上讲, 可以在不丢失自动损坏检测和修复功能的情况下将文件系统和存储卷管理系统分离为离散的层,但这不是当前存储系统的设计方式,这将给新设计带来重大挑战。
备用文件系统
在我们开始之前,提醒一句:要非常小心与不内置,直接支持为您分配的主线内核的一部分,任何备用的文件系统!
即使文件系统是安全的 ,如果在内核升级过程中出现问题,将其用作根文件系统也绝对会令人恐惧。 如果你不从备用介质引导,并从一个chroot手动和耐心地戳在内核模块,蛴螬CONFIGS和DKMS的想法非常舒适......不要去用根文件系统的预约系统上对你很重要。
使用发行版不直接支持的文件系统可能有充分的理由,但是如果这样做,我强烈建议您在系统启动并可用后挂载它。 (例如,您可能具有ext4根文件系统,但将大多数数据存储在zfs或btrfs池中。)
XFS文件
XFS与Linux下的非ext文件系统一样是主流。 这是一个64位的日志文件系统,自2001年以来已内置到Linux内核中,并为大型文件系统提供了高性能,并具有高度的并发性(即,实际上有很多进程一次写入文件系统)。
从RHEL 7开始,XFS成为Red Hat Enterprise Linux的默认文件系统。对于家庭或小型企业用户而言,它仍然具有一些缺点-最值得注意的是,调整现有XFS文件系统的大小确实很麻烦,以至于它通常会带来更多的麻烦。创建另一个并复制数据的感觉。
尽管XFS稳定且性能良好,但它与ext4之间没有足够的具体最终用途差异,因此建议在非默认值(例如RHEL7)的任何地方使用它, 除非它解决了ext4遇到的特定问题,例如> 50 TiB容量的文件系统。
与ZFS,btrfs甚至WAFL(专有SAN文件系统)相比,XFS绝不是“下一代”文件系统。 像ext4一样,在朝更好的方向前进时,它很可能被视为权宜之计。
ZFS
ZFS由Sun Microsystems开发,并以zettabyte(相当于1万亿GB)命名,因为它在理论上可以处理如此大的存储系统。
ZFS是真正的下一代文件系统,可提供卷管理(能够在单个文件系统中寻址多个单独的存储设备),块级加密校验和(允许以极高的准确率检测数据损坏), 自动损坏修复 (其中冗余或奇偶校验存储可用),快速异步增量复制 ,内联压缩等。 还有更多 。
从Linux用户的角度来看,ZFS的最大问题是许可。 ZFS已获得CDDL的许可,这是与GPL冲突的半开放许可。 关于在Linux内核中使用ZFS的含义存在很多争议,意见从“违反GPL”到“违反CDDL”到“完全正确,只是未经法院测试”。 ” 最值得注意的是,Canonical自2016年以来一直将ZFS代码内联包含在其默认内核中,到目前为止没有法律挑战。
目前,即使我自己是一个非常狂热的ZFS用户,我也不建议将ZFS作为根Linux文件系统。 如果要利用Linux上ZFS的好处,请在ext4上设置一个小的根文件系统, 然后将ZFS放在剩余的存储上,然后将数据和应用程序随心所欲地放置在ext4上,但要保持根在ext4上,直到分发为止明确地 支持zfs根目录。
btrfs
克里斯·梅森(Chris Mason)于2007年在Oracle(Oracle)任职期间宣布了Btrfs(B树文件系统的缩写,通常发音为“黄油”)。 BTRFS目的至多的相同的目标ZFS,提供多种设备管理,每块校验,异步复制,直列压缩,和更 。
截至2018年,btrfs相当稳定且可用作标准的单磁盘文件系统,但可能不应该依赖它作为卷管理器。 与ext4,XFS或ZFS相比,在许多常见用例中,它遭受了严重的性能问题,并且其下一代功能(复制,多磁盘拓扑和快照管理)可能会出现很多错误,结果可能导致灾难性的性能下降。造成实际数据丢失。
btrfs的持续状态存在争议; SUSE Enterprise Linux在2015年将其用作默认文件系统,而Red Hat宣布它将在2017年从RHEL 7.4开始不再支持btrfs。值得注意的是,生产,受支持的btrfs部署会将其用作单磁盘文件系统, ZFS甚至不是 Synology,都在其存储设备上使用btrfs 作为 ZFS,甚至没有作为多磁盘卷管理器,而是将其分层放置在常规Linux内核RAID(mdraid)上以管理磁盘。