了解ext4的历史,包括它与ext3及之前的其他文件系统的区别。现在的Linux文件系统大多默认为ext4文件系统,就像之前的Linux发行版默认为ext3、ext2和更早的ext一样。对于不熟悉Linux或文件系统的朋友,可能不知道ext4相比之前的版本ext3带来了哪些变化。您可能还想知道,在有关替代文件系统(例如Btrfs、XFS和ZFS)的大量公告中,ext4是否仍在进一步发展。我们不可能在一篇文章中涵盖文件系统的所有方面,但我们试图让您快速了解Linux默认文件系统的历史,包括它的诞生和未来的发展。我仔细研究了维基百科中关于ext文件系统的各种文章,kernel.orgwiki中的ext4条目,结合自己的经验写了这篇文章。ext简史MINIX文件系统在ext之前,使用的是MINIX文件系统。如果您不熟悉Linux的历史,MINIX是用于IBMPC/AT微型计算机的非常小的类Unix系统。AndrewTannenbaum出于教学目的开发了它,并于1987年发布了源代码(以印刷形式!)。IBM1980年代中期的PC/AT,MBlairMartin,CCBY-SA4.0虽然您可以仔细阅读MINIX的源代码,但实际上并不是免费和开源软件(FOSS)。Tannebaum的书的出版商要求您支付69美元的许可费才能运行MINIX,这已包含在本书的成本中。尽管如此,它在当时很便宜,而且MINIX的使用增长迅速,很快就超过了Tannebaum使用它来教授操作系统编码的初衷。在整个1990年代,您可以发现MINIX安装在世界各地的大学中非常流行。此时,年轻的LinusTorvalds使用MINIX开发了最初的Linux内核,该内核于1991年首次公布,随后于1992年12月在GPL开源协议下发布。但是等等,这是一篇关于文件系统的文章,不是吗?是的,MINIX有自己的文件系统,早期的Linux版本都依赖它。和MINIX一样,Linux的文件系统小得像一个玩具——MINIX文件系统最多可以处理14个字符的文件名,而且只能处理64MB的存储空间。到1991年,典型的硬盘驱动器大小已达到40-140MB。显然,Linux需要更好的文件系统。ext当Linus正在开发初出茅庐的Linux内核时,RémyCard正在研究第一代ext文件系统。ext文件系统于1992年首次实现和发布——??距Linux首次发布仅一年!--ext解决了MINIX文件系统最严重的问题。ext于1992年在Linux内核中使用了新的虚拟文件系统(VFS)抽象层。与以前的MINIX文件系统不同,ext可以处理高达2GB的存储空间并处理255个字符的文件名。但是ext并没有在很长一段时间内占据主导地位,主要是因为它原来的时间戳(每个文件只有一个时间戳,不是我们今天熟悉的inode、上次文件访问时间、最新文件修改时间Timestamp。)仅仅一年之后,ext2取代了它。ext2Rémy很快意识到ext的局限性,因此一年后他设计了ext2来替代它。虽然ext仍然植根于“玩具”操作系统,但ext2是从头开始设计为商业级文件系统,遵循BSD的Berkeley文件系统的设计原则。ext2提供了GB级的最大文件大小和TB级的文件系统大小,牢固地巩固了它在1990年代文件系统大联盟中的地位。很快它就被广泛使用,无论是在Linux内核中还是最终在MINIX中,第三方模块使其可用于MacOS和Windows。但这里仍有一些问题需要解决:ext2文件系统与1990年代的大多数文件系统一样,如果在将数据写入磁盘时系统崩溃或断电,则很容易出现灾难性的数据损坏。随着时间的推移,它们还会因碎片化(单个文件存储在多个位置,物理上分布在旋转磁盘上)而遭受严重的性能损失。尽管存在这些问题,ext2目前仍用于某些特殊情况——最常见的是,作为便携式USB驱动器的文件系统格式。ext31998年,ext2被采用6年后,StephenTweedie宣布他正在致力于改进ext2。这变成了ext3,并在2001年11月的2.4.15内核版本中被采用到主线Linux内核中。1990年代中期的PackardBellComputers、Spacekid、CC0ext2在大多数情况下在Linux发行版中运行良好,但就像FAT、FAT32、HFS和当时的其他文件系统一样-当电源关闭时容易出现灾难性损坏。如果在将数据写入文件系统时发生断电,它可能会处于所谓的不一致状态——事情只完成了一半,而另一半没有完成。这可能会导致大量与正在保存的文件无关的文件丢失或损坏,甚至会导致整个文件系统无法卸载。ext3和1990年代后期的其他文件系统,例如Microsoft的NTFS,使用日志来解决这个问题。日志是磁盘上的一个特殊分配区域,其写入存储在一个事务中;如果该事务完成了磁盘写入,则日志中的数据将提交给文件系统本身。如果系统在操作提交之前崩溃,重新启动的系统会将其识别为未完成的事务并将其回滚,就好像它从未发生过一样。这意味着正在进行的文件可能仍然会丢失,但文件系统本身保持一致并且所有其他数据都是安全的。使用ext3文件系统在Linux内核中实现了三个级别的日志记录:日志、有序和写回。日志记录是最危险的模式,在将数据和元数据提交到文件系统之前将其写入日志。这保证了正在写入的文件与整个文件系统是一致的,但它显着降低了性能。Sequential是大多数Linux发行版的默认模式;顺序模式将元数据写入日志并将数据直接提交到文件系统。顾名思义,这里的操作顺序是固定的:首先,将元数据提交到日志;其次,将数据写入文件系统,然后将日志中关联的元数据更新到文件系统。这确保在发生崩溃时,那些与不完整写入相关的元数据仍在日志中,并且文件系统可以在日志回滚时清理那些不完整的写入事务。在顺序模式下,系统崩溃可能会导致崩溃期间正在主动写入的文件中出现错误,但文件系统本身——以及未主动写入的文件——是可以保证安全的。回写是第三种模式——也是最不安全的日志记录模式。在回写模式下,与顺序模式一样,记录了元数据但不记录数据。与顺序模式不同,元数据和数据都可以以有利于最大性能的任何顺序写入。这可以显着提高性能,但安全性要低得多。虽然回写模式仍然保证了文件系统本身的安全,但在崩溃或崩溃之前写入的文件很容易丢失或损坏。与之前的ext2一样,ext3使用16位内部寻址。这意味着具有4K块大小的ext3在最大规格为16TiB的文件系统中可以处理最大2TiB的文件大小。ext4TheodoreTs'o(当时ext3的主要开发者)在2006年发布了ext4,并在两年后的2.6.28内核版本中加入了Linux主线。Ts'将ext4描述为一种临时技术,它显着扩展了ext3,但仍然依赖于旧技术。他预测ext4最终将被真正的下一代文件系统所取代。DellPrecision380工作站,LanceFisher,CCBY-SA2.0ext4在功能上与ext3非常相似,但支持大型文件系统,提高了对碎片的抵抗力,具有更高的性能和更好的时间戳。ext4与ext3这里将讨论ext3和ext4之间的一些非常具体的区别。向后兼容性ext4专门设计为尽可能与ext3向后兼容。这不仅允许将ext3文件系统就地升级到ext4;它还允许ext4驱动程序以ext3模式自动挂载ext3文件系统,因此无需维护两个独立的代码库。大型文件系统ext3文件系统使用32位寻址,这将其限制为仅支持2TiB文件大小和16TiB文件系统系统大小(这是假设块大小为4KiB,一些ext3文件系统使用更小的块大小,因此进一步受限制的)。ext4使用48位内部寻址,理论上可以在文件系统上分配最大16TiB的文件,其中文件系统最大可达1000000TiB(1EiB)。ext4早期实现中的一些用户空间程序仍然将其限制为最大大小为16TiB的文件系统,但截至2011年,e2fsprogs直接支持大于16TiB的ext4文件系统。例如,RedHatEnterpriseLinux在其合同中仅支持最大50TiB的ext4文件系统,并建议ext4卷不大于100TiB。分配改进Ext4对块在写入磁盘之前的分配方式进行了大量改进,这可以显着提高读写性能。范围范围是一系列连续的物理块(最多128MiB,假设块大小为4KiB),可以立即保留和寻址。使用范围可以减少给定文件所需的inode数量,并且可以显着减少碎片并提高写入大文件时的性能。多块分配ext3为每个新分配的块调用一次块分配器。当多个写入同时打开分配器时,很容易导致严重的碎片。但是,ext4使用延迟分配,这允许它合并写入并更好地决定如何为尚未提交的写入分配块。持久预分配当为文件预分配磁盘空间时,大多数文件系统必须在创建时将零写入文件的块。ext4允许使用fallocate()代替,这保证了空间的可用性(并尝试为其找到连续的空间)而无需先写入它。这显着提高了流式和数据库应用程序写入和未来读取写入数据的性能。延迟分配这是一个有趣且有争议的功能。延迟分配允许ext4等待分配将写入数据的实际块,直到它准备好将数据提交到磁盘。(相比之下,ext3会立即分配块,即使数据仍在写入缓存。)块的延迟分配允许文件系统更好地选择如何分配块,因为数据在缓存中累积,减少碎片(写入和稍后阅读)并显着提高性能。然而不幸的是,它增加了没有专门调用fsync()方法的程序丢失数据的可能性(当程序员想要确保数据完全刷新到磁盘时)。假设一个程序完全重写了一个文件:fd=open("file",O_TRUNC);写(fd,数据);关闭(fd);使用旧的文件系统,close(fd);足以保证文件内容Flush到磁盘。即使写操作不是严格的事务性的,如果在文件关闭后发生崩溃,也几乎没有丢失数据的风险。如果写入不成功(由于程序错误、磁盘错误、断电等),文件的原始版本和新版本都可能丢失数据或损坏。如果其他进程在写入文件时访问该文件,您将看到损坏的版本。如果其他进程打开了该文件并且不希望其内容发生变化——例如,共享库映射到多个正在运行的程序。这些进程可能会崩溃。为了避免这些问题,一些程序员完全避免使用O_TRUNC。相反,他们可能会写入一个新文件,关闭它,然后将其重命名为旧文件名:fd=open("newfile");写(fd,数据);关闭(fd);重命名(“新文件”,“文件”);在没有延迟分配的文件系统上,这足以避免上面列出的潜在损坏和崩溃问题:因为rename()是原子的,它不会被崩溃中断;并且正在运行的程序将继续引用旧文件。现在未链接版本的文件只需要有一个文件的打开文件句柄。但是由于ext4的延迟分配导致写入延迟和重新排序,rename("newfile","file")可以在newfile的内容实际写入磁盘之前执行,这就产生了再次获取错误版本文件的并行性问题。为了缓解这种情况,Linux内核(自版本2.6.30起)尝试检测这些常见代码情况并强制立即分配。这减少但不能防止数据丢失的可能性——而且它对新文件没有任何作用。如果您是开发人员,请注意:保证数据立即写入磁盘的唯一方法是正确调用fsync()。最大子目录ext3限制为32000个子目录;ext4允许最大数量的子目录。从内核版本2.6.23开始,ext4使用HTree索引来减少大量子目录的性能损失。日志校验和ext3不校验日志,这会导致内核直接控制之外的磁盘或具有自己的缓存的控制器设备出现问题。如果控制器或具有自己缓存的磁盘失去写入顺序,它可能会破坏ext3的日志事务顺序,可能会损坏在崩溃期间(或之前的某个时间)写入的文件。理论上,这个问题可以使用写屏障来解决——挂载文件系统时,在挂载选项中设置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:00UTC以来的时间,这会让我安然入睡死后。联机碎片整理ext2和ext3都不直接支持联机碎片整理——也就是说,文件系统在挂载时进行碎片整理。ext2有一个包含的实用程序e2defrag,顾名思义-它需要在文件系统未安装时离线运行。(显然,这对根文件系统来说是个大问题。)ext3的情况更糟-虽然ext3比ext2更不容易受到严重碎片的影响,但在ext3文件系统上运行e2defrag可能会导致灾难性的损坏和数据丢失。尽管ext3最初被认为“不受碎片影响”,但对同一文件(例如BitTorrent)采用大规模并行写入进程的过程清楚地表明情况并非完全如此。一些用户空间的技巧和变通方法,例如Shake,以某种方式解决了这个问题——但它们速度较慢,而且在各个方面都不如真正的、文件系统感知的、内核级碎片整理过程令人满意。ext4使用e4defrag解决了这个问题,e4defrag是一个在线的、内核模式的、文件系统感知的、块级和扩展级碎片整理实用程序。正在进行的ext4开发ext4,就像MontyPython中的瘟疫感染者曾经说过的,“我还没死呢!”虽然其主要开发人员将其视为真正的下一代文件系统的权宜之计,但有一段时间,没有一个可能的候选者准备好(由于技术或许可问题)部署为根文件系统。在未来的ext4版本中仍有一些关键特性需要开发,包括元数据校验和、高级配额支持和大分配块。元数据校验和由于ext4具有冗余超级块,因此文件系统有一种方法可以检查其中的元数据,以确定主超级块是否已损坏以及是否需要使用备用块。可以在没有校验和的情况下从损坏的超级块中恢复-但用户首先需要意识到它已损坏,然后尝试使用替代方法手动安装文件系统。因为在某些情况下,挂载一个带有损坏的主超级块的文件系统进行读写可能会造成进一步的损坏,即使是有经验的用户也无法避免,这也不是一个安全的解决方案!与Btrfs或ZFS等下一代文件系统提供的极其强大的每块校验和相比,Ext4的元数据校验和非常弱。但总比没有好。虽然检查所有事情听起来很容易!--事实上,将校验和链接到文件系统有一些重大挑战;有关详细信息,请参阅设计文档。***配额支持等等,配额?!从ext2出来的那一天起我们就有了这些!是的,但他们总是事后才想到,而且他们总是很傻。可能不值得在这里详细介绍,但设计文档列出了如何将配额从用户空间移动到内核,以及如何更正确、更有效地执行。大分配块那些讨厌的存储系统随着时间的推移变得越来越大。由于一些SSD已经使用8K硬件块大小,ext4目前对4K块的限制越来越严格。更大的存储块可以显着减少碎片并提高性能,但代价是增加“松弛”空间(当您只需要块的一部分来存储文件或文件的最后一块时剩余的空间)。您可以在设计文档中找到详细说明。ext4的实际限制ext4是一个健壮、稳定的文件系统。现在大多数人应该将它用作根文件系统,但它不能满足所有需求。让我们简要谈谈一些您不应该期望的事情——现在或将来可能:虽然ext4可以处理最大1EiB(相当于1,000,000TiB)的数据,但您真的不应该尝试这样做。除了能够记住更多块的地址之外,还有规模问题。现在ext4无法处理(而且可能永远不会)超过50-100TiB的数据。ext4也不足以保证数据完整性。随着ext3时代日志记录的重大进步,它并没有涵盖数据损坏的许多常见原因。如果磁盘上的数据已经损坏——由于硬件故障、宇宙射线的影响(是的,真的),或者只是数据随时间衰减——ext4无法检测或修复这种损坏。基于以上两点,ext4只是一个纯粹的文件系统,并不是存储卷管理器。这意味着即使您有多个磁盘——也就是奇偶校验或冗余,理论上您可以从ext4恢复损坏的数据,但无法知道使用它是否对您有利。虽然理论上可以在不丢失自动损坏检测和修复功能的情况下将不同层的文件系统和存储卷管理系统分开,但这不是当前存储系统的设计方式,它将对新设计提出重大挑战。替代文件系统在我们开始之前,请注意:要非常小心,没有内置的替代文件系统,也没有作为主线内核的一部分直接支持的替代文件系统!即使文件系统是安全的,如果在内核升级期间出现问题,将其用作根文件系统也是非常可怕的。如果您没有充分的理由通过chroot从替代媒体启动,请耐心等待内核模块、grub配置和DKMS……不要删除非平凡系统上保留的根文件。可能有充分的理由使用您的发行版不直接支持的文件系统-但如果您这样做,我强烈建议您在系统启动并可用后安装它。(例如,您可能有一个ext4根文件系统,但将大部分数据存储在ZFS或Btrfs池中。)XFSXFS与Linux主线中的非ext文件系统具有相同的地位。它是自2001年以来内置于Linux内核中的64位日志文件系统,可为大型文件系统和高并发性(即大量进程同时写入文件系统)提供高性能。从RHEL7开始,XFS是RedHatEnterpriseLinux的默认文件系统。对于家庭或小型企业用户,它仍然有一些缺点——最值得注意的是,调整现有XFS文件系统的大小非常痛苦,因此创建另一个文件系统并将数据复制过来可能更有意义。虽然XFS是稳定和高性能的,但它和ext4之间没有足够的具体最终用途差异来保证推荐它在非默认的任何地方使用(如RHEL7),除非它解决了ext4的特定问题,例如容量大于50TiB的文件系统。XFS在任何方面都不是ZFS、Btrfs甚至WAFL(一种专有的SAN文件系统)的“下一代”文件系统。与ext4一样,它应该被视为更好方法的权宜之计。ZFSZFS由SunMicrosystems开发并以zettabyte(相当于1万亿千兆字节)命名,因为它理论上可以处理大型存储系统。作为真正的下一代文件系统,ZFS提供卷管理(能够在单个文件系统中处理多个独立的存储设备)、块级加密校验和(允许以非常高的准确度检测数据损坏)、自动损坏修复(冗余或奇偶校验存储可用)、快速异步增量复制、内联压缩等。从Linux用户的角度来看,ZFS的最大问题是许可问题。ZFS许可证是CDDL许可证,它是一个与GPL冲突的半宽容许可证。关于在Linux内核中使用ZFS意味着什么,有很多争论,从“违反GPL”到“违反CDDL”再到“完全没问题,还没有在法庭上测试过”。最值得一提的是,自2016年以来,Canonical已将ZFS代码内联到其默认内核中,目前没有任何法律挑战。在这一点上,即使我是一个非常狂热的ZFS用户,我也不会推荐ZFS作为Linux的根文件系统。如果你想在Linux上利用ZFS,用ext4设置一个小的根文件系统,然后在你的其余存储上使用ZFS,把数据、应用程序,任何你喜欢的东西放在上面——但是把根分区保留在ext4上,直到您的发行版明确支持ZFSroot。BtrfsBtrfs是B-TreeFilesystem的缩写,通常发音为“butter”——由ChrisMason在2007年在Oracle任职期间发布。Btrfs旨在实现与ZFS大部分相同的目标,提供各种设备管理、每块校验和、异步复制、内联压缩等,等等。截至2018年,Btrfs相当稳定,可以用作标准的单磁盘文件系统,但可能不应该依赖它作为卷管理器。在许多常见用例中,与ext4、XFS或ZFS相比,它存在严重的性能问题,其下一代功能——复制、多磁盘拓扑和快照管理——可能会让人不知所措,其结果可能是灾难性的性能降低实际数据丢失。Btrfs的维护状态是有争议的;SUSEEnterpriseLinux在2015年采用它作为默认文件系统,而RedHat在2017年宣布从RHEL7.4开始不再支持Btrfs。可能值得注意的是,该产品支持将Btrfs部署为单磁盘文件系统,而不是像ZFS中那样作为多磁盘卷管理器,甚至Synology也将Btrfs用于其存储设备,但它在传统的Linux内核RAID中这样做(mdraid)在其之上层管理磁盘。
