Linux内核源码:ext4 extent详解
在 Linux 系统的庞大体系中,文件系统就像是一个井然有序的图书馆,而 ext4 文件系统则是这座图书馆中极为重要的 “藏书室”,它负责高效管理和存储数据。在 ext4 众多的奥秘中,ext4 extent 犹如一颗璀璨的明珠,起着关键作用。
接下来,我将带大家深入到 Linux 内核源码的世界,详细解读 ext4 extent。在这趟旅程中,我们会剖析它的诞生背景、核心数据结构,以及它在文件操作里的运行机制,让你对 Linux 文件系统的底层原理有更透彻的理解。准备好了吗?一起开启这场精彩的探索吧!
一、什么是ext4 extent?
在 Linux 系统的广袤世界里,文件系统如同坚实的基石,支撑着数据的有序存储与高效管理。而 ext4 文件系统,作为 Linux 系统中广泛应用的文件系统,凭借其卓越的性能、强大的稳定性以及出色的兼容性,成为众多用户的信赖之选。它不仅是 Linux 系统的默认文件系统,更是数据存储与管理的中流砥柱,在服务器、个人电脑等各种应用场景中都发挥着不可或缺的关键作用。
在 ext4 文件系统中,extent 扮演着举足轻重的角色,堪称其核心与灵魂所在。它的出现,彻底革新了文件数据的存储与管理方式,为提升文件系统的性能开辟了全新的路径。传统的文件系统在处理文件数据时,往往采用直接映射或间接映射的方式,将文件的逻辑块号映射到物理块号。
这种方式虽然在一定程度上能够满足基本的存储需求,但在面对大文件时,却暴露出诸多严重的弊端。随着文件规模的不断增大,映射表的规模也会急剧膨胀,导致占用大量的磁盘空间和内存资源。同时,由于映射关系的复杂性,文件的读写操作需要频繁地访问映射表,这不仅增加了系统的开销,还严重影响了文件的读写速度。
而 extent 的诞生,为解决这些问题带来了曙光。它以一种全新的视角和方式,对文件数据的存储进行了优化和重构。extent 的核心思想是将文件中的数据划分为若干个连续的物理块,这些连续的物理块被视为一个整体,即 extent。通过这种方式,文件的数据不再是零散地分布在磁盘的各个角落,而是以连续的块组形式存储,大大提高了数据的存储密度和连续性。这种连续性存储方式带来了诸多显著的优势。
首先,它减少了文件数据的碎片化程度,使得文件在磁盘上的存储更加紧凑和有序。这不仅有助于提高磁盘空间的利用率,还能减少文件读写时的寻道时间和旋转延迟,从而显著提升文件的读写性能。其次,extent 的使用简化了文件的映射关系,使得文件的逻辑块号与物理块号之间的映射更加直观和高效。通过 extent,文件系统可以直接定位到文件数据所在的物理块,无需像传统方式那样进行复杂的映射表查询,大大提高了文件的访问速度和效率。
在实际应用中,extent 的优势得到了充分的体现。例如,在处理大型数据库文件时,extent 能够确保数据库文件的数据连续存储,使得数据库的读写操作更加高效和稳定。这对于提高数据库的性能和响应速度具有重要意义,能够满足企业级应用对数据处理的高要求。又如,在进行大规模文件传输时,extent 的连续性存储方式可以减少文件传输过程中的中断和错误,提高文件传输的成功率和速度。这对于需要频繁进行文件传输的场景,如数据备份、文件共享等,具有重要的实用价值。
extent 作为 ext4 文件系统的核心特性,以其独特的设计理念和高效的实现方式,为文件数据的存储和管理带来了革命性的变革。它不仅解决了传统文件系统在处理大文件时面临的诸多问题,还为提升文件系统的性能和可靠性奠定了坚实的基础。在未来的发展中,随着数据量的不断增长和应用需求的日益多样化,extent 必将继续发挥其重要作用,为 Linux 系统的发展和应用提供强有力的支持。
二、ext4 entent 的诞生背景
2.1ext2、ext3 文件系统的寻址方式
在深入探讨 ext4 extent 之前,让我们先回顾一下 ext2 和 ext3 文件系统的寻址方式。ext2 作为 Linux 系统中早期广泛使用的文件系统,于 1992 年诞生,它为 Linux 系统的文件存储和管理奠定了基础。而 ext3 则在 2001 年出现,它在 ext2 的基础上增加了日志功能,大大提高了文件系统的可靠性和稳定性。在当时的技术背景下,ext2 和 ext3 文件系统采用的是直接 + 间接寻址的方式来实现文件逻辑地址到物理块地址的映射。这种寻址方式虽然在一定程度上满足了文件存储和访问的需求,但随着时间的推移和数据量的不断增长,其局限性也逐渐显现出来。
具体来说,ext2 和 ext3 文件系统的寻址方式可以进一步细化为 1 - 3 级间接寻址。以 inode 结构体中的 i_block 数组为例,这个数组在文件寻址过程中扮演着至关重要的角色。i_block 数组中有 15 个元素,其中前 12 个元素用于直接寻址。这意味着,对于那些较小的文件,其数据块的地址可以直接存储在这 12 个元素中。当文件需要读取或写入数据时,系统可以直接通过这些元素找到对应的物理块,从而快速地访问文件数据。这种直接寻址方式简单高效,能够满足大多数小型文件的存储和访问需求。
然而,对于较大的文件,仅靠直接寻址是远远不够的。这时,就需要借助间接寻址来扩展寻址能力。i_block 数组的第 13 个元素用于一级间接寻址。在一级间接寻址中,这个元素指向一个块,而这个块中存储的是一系列数据块的地址。通过这种方式,系统可以通过一级间接寻址访问到更多的数据块,从而支持更大文件的存储。当文件的大小超过了直接寻址的范围时,系统会首先找到 i_block 数组的第 13 个元素,然后根据这个元素指向的块,读取其中存储的数据块地址,进而访问到相应的数据块。
如果文件的大小继续增大,一级间接寻址也无法满足需求时,就需要使用二级间接寻址。i_block 数组的第 14 个元素用于二级间接寻址。在二级间接寻址中,这个元素指向的块中存储的不是数据块的地址,而是指向其他块的地址,这些其他块中才存储着数据块的地址。通过这种两层间接的方式,系统可以进一步扩展寻址范围,以支持更大文件的存储。在实际操作中,系统会先找到 i_block 数组的第 14 个元素,然后根据这个元素指向的块,读取其中存储的其他块的地址,再从这些其他块中读取数据块的地址,最终访问到相应的数据块。
对于那些极其庞大的文件,二级间接寻址也可能不够用,这时就需要用到三级间接寻址。i_block 数组的第 15 个元素用于三级间接寻址。三级间接寻址的原理与二级间接寻址类似,只是增加了一层间接性。通过这种方式,系统可以实现对非常大的文件的寻址,满足用户对大容量文件存储和访问的需求。在三级间接寻址中,系统需要经过多层的地址查找,才能最终找到数据块的地址。
2.2传统寻址方式的弊端
ext2 和 ext3 文件系统的传统寻址方式虽然在一定时期内发挥了重要作用,但随着数据量的爆炸式增长和应用场景的日益复杂,其弊端也逐渐暴露无遗。这些弊端不仅限制了文件系统的性能和扩展性,也给用户的使用带来了诸多不便。
传统寻址方式存在着严重的磁盘空间浪费问题。在这种寻址方式下,文件的数据块是按照离散的方式存储在磁盘上的,即使文件的数据块在逻辑上是连续的,它们在物理磁盘上也可能分布在不同的位置。这就导致了磁盘空间的碎片化,使得磁盘上出现了大量的零散空闲块,这些空闲块由于太小而无法被有效利用,从而造成了磁盘空间的浪费。当一个文件被删除后,其占用的磁盘空间被释放,但这些释放的空间可能会被分割成多个小块,散布在磁盘的不同位置。后续如果有新的文件需要存储,这些零散的空闲块可能无法满足新文件的连续存储需求,导致新文件不得不被存储在多个不连续的块中,进一步加剧了磁盘空间的碎片化。
传统寻址方式在处理大文件时,寻址效率极低。对于大文件来说,由于其数据块数量众多,需要通过多级间接寻址才能找到所有的数据块。在这个过程中,系统需要频繁地读取磁盘上的间接块,以获取数据块的地址,这不仅增加了磁盘 I/O 的次数,也大大降低了文件的访问速度。在访问一个大型数据库文件时,可能需要经过多次的一级、二级甚至三级间接寻址才能找到所需的数据块,这使得文件的读取时间大幅增加,严重影响了应用程序的性能。
传统寻址方式还容易导致文件碎片化。随着文件的不断创建、删除和修改,磁盘上的文件数据块会逐渐变得零散,这不仅会降低文件的访问速度,还会增加文件系统的维护难度。当一个文件被频繁修改时,其数据块可能会被分散到不同的位置,导致文件的碎片化程度不断加深。这不仅会增加文件读取时的寻道时间,还可能导致文件系统在进行磁盘整理时需要花费更多的时间和资源。
为了解决这些问题,ext4 文件系统引入了 extent 机制。extent 机制的出现,彻底改变了文件数据的存储和管理方式,为提升文件系统的性能和扩展性提供了有效的解决方案。通过将文件的数据块组织成连续的 extent,extent 机制大大减少了磁盘空间的浪费和文件碎片化的问题,同时提高了文件的寻址效率和访问速度。在 extent 机制下,文件的数据块可以以连续的方式存储在磁盘上,减少了间接寻址的次数,提高了文件的访问效率。extent 机制还可以更好地利用磁盘的顺序读写性能,进一步提升文件系统的整体性能。
三、ext4 extent 的数据结构剖析
ext4 extent 的高效运作离不开其精心设计的数据结构。这些数据结构犹如精密的齿轮,相互协作,共同构建了 ext4 文件系统强大的数据管理能力。接下来,让我们深入剖析 ext4 extent 中三个关键的数据结构:ext4_extent、ext4_extent_header 和 ext4_extent_idx,探寻它们的奥秘。
3.1ext4_extent 结构
ext4_extent 结构是 ext4 extent 机制的核心组成部分,它就像是一座桥梁,紧密地连接着文件的逻辑块地址和物理块地址,为文件数据的存储和访问提供了关键的映射关系。其结构体定义如下:
struct ext4_extent {__le32 ee_block; // 起始逻辑块地址__le16 ee_len; // 映射的连续物理块个数__le16 ee_start_hi; // 起始物理块地址的高16位__le32 ee_start_lo; // 起始物理块地址的低32位
};
在这个结构体中,各个成员都肩负着重要的使命。ee_block 成员记录的是起始逻辑块地址,它就像是文件数据旅程的起点,明确了文件逻辑地址的起始位置。通过这个成员,系统能够准确地定位到文件在逻辑层面的起始位置,为后续的数据访问提供了基础。
ee_len 成员则表示映射的连续物理块个数,它清晰地界定了 extent 所涵盖的物理块范围。这个成员的存在,使得系统能够快速了解到文件数据在物理存储上的连续程度,从而合理地安排数据的读写操作。
ee_start_hi 和 ee_start_lo 成员共同构成了起始物理块地址。其中,ee_start_lo 保存的是起始物理块地址的低 32 位,而 ee_start_hi 保存的是高 16 位。通过这两个成员的组合,系统可以精确地确定文件数据在磁盘上的起始物理位置,实现从逻辑地址到物理地址的准确映射。
例如,当我们有一个 ext4_extent 结构,其中 ee_block 为 100,ee_len 为 5,ee_start_hi 为 0x1234,ee_start_lo 为 0x56789abc 时,这就表示文件的逻辑块地址从 100 开始,连续 5 个逻辑块,对应到物理块地址则是从 0x123456789abc 开始的连续 5 个物理块。通过这种方式,ext4_extent 结构简洁而高效地实现了文件逻辑块与物理块的映射关系,为文件系统的高效运作提供了有力支持。
3.2ext4_extent_header 结构
ext4_extent_header 结构是 ext4 extent 数据结构中的重要组成部分,它主要用于保存叶子节点或索引节点的统计信息,为整个 ext4 extent 机制的运行提供了关键的元数据支持。其结构体定义如下:
struct ext4_extent_header {__le16 eh_magic; // 魔数,用于标识结构类型__le16 eh_entries; // 有效条目数__le16 eh_max; // 最大条目数__le16 eh_depth; // 树深度__le32 eh_generation; // 世代
};
在这个结构体中,每个成员都有着独特的作用和意义。eh_magic 是魔数,它就像是一把独特的钥匙,用于标识该结构的类型。通过魔数,系统可以快速识别出该结构是否为 ext4_extent_header,确保数据的正确解析和处理。在文件系统的运行过程中,当需要读取和处理 ext4_extent 相关的数据时,首先会通过 eh_magic 来判断数据结构的类型,以保证后续操作的准确性。
eh_entries 表示当前节点中有效的 ext4_extent_idx 或 ext4_extent 的个数。这个成员就像是一个计数器,记录着节点中实际使用的条目数量。系统可以根据这个值来确定节点中有效数据的数量,从而合理地进行数据的读取和处理。在遍历 ext4 extent B + 树时,通过 eh_entries 可以快速了解每个节点中有效条目的数量,提高遍历效率。
eh_max 则表示该节点最多可以保存的 ext4_extent_idx 或 ext4_extent 的个数。它为节点的存储容量设定了上限,帮助系统在进行数据插入和管理时进行合理的规划。当需要向节点中插入新的条目时,系统会先检查 eh_max 的值,以确保不会超出节点的存储容量。
eh_depth 记录了当前叶子节点或者索引节点在 B + 树中所处的层数。这个成员对于理解 B + 树的结构和进行树的遍历操作至关重要。通过 eh_depth,系统可以清晰地知道当前节点在树中的位置,从而准确地进行数据的查找和定位。在查找文件的逻辑块地址对应的物理块地址时,需要根据 eh_depth 来确定遍历 B + 树的路径和层次。
eh_generation 是一个世代号,主要用于检测树结构的一致性。在文件系统的运行过程中,可能会因为各种原因导致树结构的变化,而 eh_generation 可以帮助系统检测这些变化,确保树结构的完整性和一致性。当文件系统进行某些操作,如文件的创建、删除或修改时,eh_generation 会相应地更新,系统可以通过比较不同时刻的 eh_generation 值来判断树结构是否发生了异常变化。
3.3ext4_extent_idx 结构
ext4_extent_idx 结构在 ext4 extent B + 树中扮演着索引的关键角色,它就像是一个精准的导航仪,帮助系统在庞大的文件系统中快速定位到所需的 ext4_extent 结构,进而实现文件逻辑块地址到物理块地址的高效映射。其结构体定义如下:
struct ext4_extent_idx {__le32 ei_block; // 起始逻辑块地址__le32 ei_leaf_lo; // 指向物理块地址的低32位__le16 ei_leaf_hi; // 指向物理块地址的高16位__u16 ei_unused; // 未使用字段
};
在这个结构体中,ei_block 成员记录的是起始逻辑块地址,它是索引的关键依据。系统在进行文件逻辑块地址查找时,首先会根据 ei_block 的值来确定查找的范围和方向。通过比较待查找的逻辑块地址与 ei_block 的值,系统可以快速定位到可能包含目标 ext4_extent 结构的节点。
ei_leaf_lo 和 ei_leaf_hi 成员共同组成了指向对应物理块地址的指针。其中,ei_leaf_lo 保存的是物理块地址的低 32 位,ei_leaf_hi 保存的是高 16 位。这两个成员的组合,使得系统能够准确地定位到 ext4_extent 结构所在的物理块,从而获取到文件逻辑块与物理块的映射关系。在 ext4 extent B + 树的遍历过程中,当找到包含目标逻辑块地址的 ext4_extent_idx 结构后,通过 ei_leaf_lo 和 ei_leaf_hi 的值,系统可以直接访问到对应的 ext4_extent 结构,实现快速的数据检索。
ei_unused 字段目前尚未被使用,它为未来的功能扩展预留了空间。随着文件系统的发展和需求的变化,这个字段可能会被赋予新的功能,以满足不断增长的应用需求。
四、ext4 extent B+树的构建与工作机制
4.1 B+ 树的基本概念
在计算机科学的浩瀚领域中,B+树作为一种平衡多路查找树,犹如一颗璀璨的明星,在数据存储和检索的舞台上闪耀着独特的光芒。它的设计理念精妙绝伦,专门为外存存储场景量身定制,旨在高效地处理大规模数据的存储与访问。在 ext4 文件系统中,B+树更是扮演着举足轻重的角色,它如同一位精准的导航者,巧妙地组织着 ext4_extent 结构,为文件数据的快速定位和访问提供了坚实的保障。
B+树的独特魅力源于其卓越的结构设计。它的所有叶子节点整齐地排列在同一层,形成了一个有序的链表结构。这种结构使得范围查询变得轻而易举,就像在一本按字母顺序排列的词典中查找某个单词范围一样,能够迅速定位到所需的信息。同时,内部节点仅存储关键字,这些关键字如同一个个索引标签,指引着搜索的方向,大大减少了树的高度,提高了查询效率。这就好比在一个大型图书馆中,通过书架上的分类标签,读者可以快速找到自己需要的书籍所在的大致区域,而无需在茫茫书海中盲目寻找。
在实际应用中,B+树的优势得到了淋漓尽致的体现。以数据库索引为例,B+树能够快速定位到满足特定条件的数据记录,大大提高了数据库的查询性能。在文件系统中,B+树则能够高效地管理文件的物理存储位置,使得文件的读写操作更加迅速和稳定。
4.2 ext4 extent B + 树的节点组成
ext4 extent B+树作为ext4 文件系统中组织 ext4_extent 结构的关键数据结构,其节点组成精妙而严谨,每个部分都承载着独特的使命,共同构建了高效的数据管理体系。
根节点作为 B + 树的核心枢纽,由 1 个 ext4_extent_header 和 4 个 ext4_extent_idx 组成。ext4_extent_header 如同根节点的 “大脑”,保存着至关重要的统计信息。其中,eh_magic 作为魔数,是识别该节点类型的关键标识,确保系统能够准确无误地解析节点信息。eh_entries 记录着当前根节点中有效的 ext4_extent_idx 的个数,让系统清楚了解节点的使用情况。eh_max 则限定了根节点最多可容纳的 ext4_extent_idx 的数量,为数据的存储提供了边界限制。eh_depth 记录着根节点在B+ 树中的层次,帮助系统在遍历树结构时确定路径。eh_generation 作为世代号,用于检测树结构的一致性,保障数据的完整性。而 4 个 ext4_extent_idx 则像是根节点伸出的 “触角”,每个 ext4_extent_idx 都记录着起始逻辑块地址,通过 ei_leaf_lo 和 ei_leaf_hi 共同组成的指针,指向第 2 层的索引节点,为数据的查找指引方向。
索引节点在B+ 树中起着承上启下的重要作用,由 1 个 ext4_extent_header 和 N 个 ext4_extent_idx 组成。这里的 ext4_extent_header 同样保存着与根节点类似的统计信息,为索引节点的管理和操作提供依据。N 个 ext4_extent_idx 则根据文件的实际情况而变化,它们各自记录着起始逻辑块地址,并通过指针指向第 3 层的叶子节点。这些 ext4_extent_idx 就像是连接根节点和叶子节点的桥梁,使得系统能够沿着逻辑块地址的线索,逐步深入到叶子节点,找到所需的数据。
叶子节点是 B+树中存储实际数据的关键部分,由 1 个 ext4_extent_header 和 N 个 ext4_extent 组成。ext4_extent_header 保存的统计信息对于叶子节点的管理至关重要。而 N 个 ext4_extent 则是文件逻辑块地址与物理块地址映射关系的具体体现。每个 ext4_extent 都记录着起始逻辑块地址、映射的连续物理块个数以及起始物理块地址,这些信息如同精准的地图,让系统能够准确无误地找到文件数据在磁盘上的存储位置。
通过这样的节点组成方式,ext4 extent B+树构建了一个层次分明、结构严谨的数据管理体系。从根节点到索引节点,再到叶子节点,每一层都紧密协作,为文件数据的高效存储和快速检索提供了坚实的保障。在实际的文件系统操作中,无论是文件的读取、写入还是删除,B+树都能够迅速响应,满足系统和用户的需求。
4.3 B+树的构建过程
ext4 extent B + 树的构建过程是一个随着文件写入数据不断动态变化和优化的过程,它如同一场精密的舞蹈,每一个动作都协调有序,确保文件数据能够高效地存储和管理。
当一个新文件被创建时,ext4 会为其初始化一棵空的 ext4 extent B+树。此时的 B+ 树就像一张白纸,等待着数据的填充。随着文件开始写入数据,ext4 会根据数据的逻辑块地址和物理块地址的映射关系,逐步构建 B + 树的结构。
假设我们有一个文件,在写入数据的初期,数据量较小,ext4 会尝试将 ext4_extent 结构直接存储在 inode 的 i_data 数组中。这就像是在一个小房间里存放物品,物品数量不多时,可以直接放在房间的显眼位置,方便取用。但随着文件数据的不断增加,i_data 数组的空间逐渐变得紧张,当无法容纳更多的 ext4_extent 结构时,ext4 就会着手将这些 ext4_extent 结构组织成 B + 树。
具体来说,当需要插入一个新的 ext4_extent 结构时,系统会首先从根节点开始查找。根节点中的 ext4_extent_idx 会根据起始逻辑块地址,与待插入的 ext4_extent 结构的起始逻辑块地址进行比较。如果找到一个合适的 ext4_extent_idx,其指向的索引节点能够容纳新的 ext4_extent 结构,那么系统会将新的 ext4_extent 结构插入到该索引节点中。这就像是在一个书架上找到一个合适的格子,将新书放入其中。
然而,如果索引节点已满,无法容纳新的 ext4_extent 结构,这时就会触发节点的分裂操作。系统会创建一个新的索引节点,将原索引节点中的部分 ext4_extent_idx 和新的 ext4_extent 结构合理地分配到两个节点中。同时,为了保持 B + 树的结构完整性和查询效率,还需要更新根节点中相关的 ext4_extent_idx,使其正确地指向新的索引节点。这一过程就像是将一个装满书的书架分成两个书架,并重新整理书架上的书籍分类标签,以确保读者能够快速找到所需的书籍。
在叶子节点层面,当插入新的 ext4_extent 结构时,如果叶子节点还有空间,就直接插入。但如果叶子节点已满,同样会进行分裂操作。新的叶子节点会被创建,原叶子节点中的 ext4_extent 结构会被合理分配到两个叶子节点中。同时,上层的索引节点中的 ext4_extent_idx 也需要相应地更新,以准确指向新的叶子节点。
随着文件数据的持续增加,B + 树会不断地进行这样的插入、分裂和更新操作,逐渐成长为一个能够高效管理大量文件数据的复杂结构。这个过程不仅体现了 ext4 extent B + 树的动态适应性和灵活性,也为文件系统在面对各种规模文件时提供了高效的数据存储和管理能力。无论是小型文件还是大型文件,B + 树都能够根据文件的实际情况,合理地组织 ext4_extent 结构,确保文件数据的快速访问和存储。
4.4通过B+ 树查找物理块地址
在 ext4 文件系统中,通过 ext4 extent B+ 树查找物理块地址是一个高效而有序的过程,它就像是在一座精心构建的图书馆中查找一本特定的书籍,每一步都有明确的指引,确保能够迅速准确地找到目标。
假设我们要查找一个文件的某个逻辑块地址对应的物理块地址。首先,我们从 ext4 extent B + 树的根节点出发。根节点中的 ext4_extent_header 记录着重要的统计信息,而 4 个 ext4_extent_idx 则是我们查找的起点。系统会将待查找的逻辑块地址与根节点中 ext4_extent_idx 的起始逻辑块地址进行比较。比如,我们要查找逻辑块地址为 50 的物理块地址,根节点中有 4 个 ext4_extent_idx,它们的起始逻辑块地址分别为 0、20、40、60。通过比较,我们发现 40 是最接近 50 且小于 50 的起始逻辑块地址,于是我们顺着这个 ext4_extent_idx 指向的指针,来到对应的索引节点。
在索引节点中,同样有一个 ext4_extent_header 和多个 ext4_extent_idx。我们再次将逻辑块地址 50 与索引节点中 ext4_extent_idx 的起始逻辑块地址进行比较。假设这个索引节点中有 5 个 ext4_extent_idx,起始逻辑块地址分别为 40、45、50、55、60。通过比较,我们找到起始逻辑块地址为 45 的 ext4_extent_idx,因为它是最接近 50 且小于 50 的。然后,我们顺着这个 ext4_extent_idx 指向的指针,来到对应的叶子节点。
在叶子节点中,包含了 1 个 ext4_extent_header 和多个 ext4_extent 结构。每个 ext4_extent 结构都记录着一段逻辑块地址与物理块地址的映射关系。我们将逻辑块地址 50 与叶子节点中 ext4_extent 的起始逻辑块地址进行比较。假设叶子节点中有 3 个 ext4_extent 结构,起始逻辑块地址分别为 40、45、55。我们找到起始逻辑块地址为 45 的 ext4_extent 结构,通过计算可以确定逻辑块地址 50 在这个 ext4_extent 结构中的偏移量,再结合 ext4_extent 结构中记录的起始物理块地址,就可以准确地计算出逻辑块地址 50 对应的物理块地址。
通过这样的方式,ext4 extent B + 树能够快速准确地将文件的逻辑块地址映射到物理块地址,实现高效的数据访问。这种查找机制不仅体现了 B + 树结构的优越性,也为 ext4 文件系统的高性能提供了有力支持。在实际应用中,无论是读取文件数据还是写入文件数据,都能够通过这种方式迅速定位到所需的物理块,大大提高了文件系统的操作效率。
五、ext4 extent 在文件操作中的应用
5.1文件读取流程
在 ext4 文件系统中,文件读取是一个涉及多个关键步骤和函数的复杂过程,其中 ext4_ext_map_blocks 函数起着核心作用,它巧妙地利用 ext4 extent B + 树,将文件的逻辑地址精准地转换为物理地址,为文件数据的读取奠定了基础。
当应用程序发起文件读取请求时,首先会调用 ext4_readpage 函数。这个函数就像是文件读取流程的入口,它接收文件的相关信息,如文件的 inode、要读取的页面等。接着,ext4_readpage 会调用 page_readpages 函数,该函数负责组织和管理页面的读取操作,它会将读取请求进一步传递给 ext4_get_block 函数。
ext4_get_block 函数是文件读取流程中的关键环节,它的主要任务是获取文件数据所在的物理块。在这个过程中,ext4_get_block 会调用_ext4_get_block 函数,进一步深入到文件系统的内部,查找文件数据的物理位置。而_ext4_get_block 函数又会调用 ext4_map_blocks 函数,开始真正的逻辑地址到物理地址的映射过程。
ext4_map_blocks 函数在接收到文件的逻辑地址和其他相关参数后,会根据文件系统的特性和配置,选择合适的映射方式。如果文件系统采用了 extent 机制,那么 ext4_map_blocks 函数会调用 ext4_ext_map_blocks 函数,利用 ext4 extent B + 树进行逻辑地址到物理地址的映射。
ext4_ext_map_blocks 函数的工作流程十分精细。它首先会在 ext4 extent B + 树的每一层索引节点(包括根节点)中,通过二分查找等高效算法,找到起始逻辑块地址最接近传入的起始逻辑块地址的 ext4_extent_idx 结构,并将其保存到一个路径数组 path 中。这个过程就像是在一本详细的地图册中,根据目的地的大致位置,找到最接近的区域索引。接着,它会沿着这个路径,找到最后一层的叶子节点中最接近传入的起始逻辑块地址的 ext4_extent 结构,并将其保存到 path 数组的相应位置。这个 ext4_extent 结构才真正包含了逻辑块地址和物理块地址的映射关系,就像是找到了目的地的详细地址。
例如,假设我们要读取一个文件中逻辑块地址为 100 的物理块地址。ext4_ext_map_blocks 函数会从 ext4 extent B + 树的根节点开始查找。根节点中的 ext4_extent_idx 会根据起始逻辑块地址进行比较,找到最接近 100 且小于 100 的起始逻辑块地址对应的 ext4_extent_idx,然后顺着这个 ext4_extent_idx 指向的指针,来到对应的索引节点。在索引节点中,再次进行类似的比较和查找,找到最接近 100 的 ext4_extent_idx,进而找到对应的叶子节点。在叶子节点中,通过比较 ext4_extent 的起始逻辑块地址,找到包含逻辑块地址 100 的 ext4_extent 结构。
找到对应的 ext4_extent 结构后,ext4_ext_map_blocks 函数会根据该结构中的信息,计算出逻辑块地址对应的物理块地址。它会根据 ext4_extent 结构中的起始逻辑块地址、映射的连续物理块个数以及起始物理块地址等信息,进行精确的计算。例如,如果找到的 ext4_extent 结构中,起始逻辑块地址为 90,映射的连续物理块个数为 20,起始物理块地址为 200,那么逻辑块地址 100 对应的物理块地址就是 200 + (100 - 90) = 210。
通过这样的方式,ext4_ext_map_blocks 函数成功地将文件的逻辑地址转换为物理地址,为后续的数据读取提供了准确的位置信息。之后,系统会根据计算得到的物理块地址,从磁盘中读取相应的数据块,将数据传递给应用程序,完成文件的读取操作。
5.2文件写入流程
文件写入是一个涉及确定数据存储位置、分配物理块以及更新 ext4 extent B + 树等多个关键步骤的复杂过程,每一个步骤都紧密相连,共同确保文件数据能够准确、高效地存储到磁盘中。
当应用程序发起文件写入请求时,首先会调用 ext4_writepage 函数。这个函数就像是文件写入流程的大门,它接收文件的相关信息,如文件的 inode、要写入的页面等。接着,ext4_writepage 会调用 ext4_get_block 函数,开始为写入的数据寻找合适的存储位置。
ext4_get_block 函数在接收到写入请求后,会根据文件的逻辑地址,在 ext4 extent B + 树中查找对应的物理块。如果找到的物理块已经被占用,或者需要分配新的物理块来存储写入的数据,ext4_get_block 函数会调用 ext4_mb_new_blocks 函数来分配物理块。
ext4_mb_new_blocks 函数会根据文件系统的空闲块管理机制,从磁盘的空闲块中选择合适的物理块分配给文件。在分配物理块时,它会考虑多种因素,以确保分配的物理块能够满足文件的存储需求。它会优先选择与文件现有数据块相邻的物理块,以提高数据的连续性和读写性能。这样,当文件后续进行读取操作时,可以减少磁盘寻道时间,提高读取效率。它还会考虑磁盘的负载均衡,避免某些区域的磁盘块被过度使用,而其他区域的磁盘块闲置,从而提高整个磁盘的利用率。
分配好物理块后,ext4_get_block 函数会根据分配的物理块信息,创建新的 ext4_extent 结构。这个新的 ext4_extent 结构会记录起始逻辑块地址、映射的连续物理块个数以及起始物理块地址等重要信息。例如,如果分配的物理块起始地址为 100,连续分配了 5 个物理块,对应的逻辑块地址从 20 开始,那么新创建的 ext4_extent 结构中,ee_block 为 20,ee_len 为 5,ee_start_lo 和 ee_start_hi 组合表示起始物理块地址 100。
接下来,ext4_get_block 函数会调用 ext4_ext_insert_extent 函数,将新创建的 ext4_extent 结构插入到 ext4 extent B + 树中。ext4_ext_insert_extent 函数会根据 ext4 extent B + 树的结构和算法,找到合适的位置插入新的 ext4_extent 结构,同时更新相关的节点信息,以维护 B + 树的平衡和一致性。它会从根节点开始查找,根据 ext4_extent 结构的起始逻辑块地址,与节点中的 ext4_extent_idx 或 ext4_extent 的起始逻辑块地址进行比较,确定插入的位置。如果插入位置的节点已满,它会进行节点分裂等操作,确保新的 ext4_extent 结构能够成功插入。
在插入过程中,ext4_ext_insert_extent 函数还会更新 ext4 extent B + 树的相关统计信息,如节点中的有效条目数、树的深度等。如果插入新的 ext4_extent 结构导致某个节点的有效条目数增加,它会更新该节点的 eh_entries 成员。如果插入操作导致树的结构发生变化,如节点分裂或合并,它会相应地更新 eh_depth 等成员,以保证 B + 树的结构正确。
通过这样的方式,ext4 文件系统完成了文件写入操作,将应用程序写入的数据准确地存储到磁盘中,并更新了 ext4 extent B + 树的结构和信息,为后续的文件操作提供了准确的映射关系。
5.3文件扩展与收缩
在文件的生命周期中,文件扩展与收缩是常见的操作,它们直接关系到文件在磁盘上的存储布局和空间利用效率。在 ext4 文件系统中,文件扩展与收缩的实现依赖于 ext4 extent 机制和 ext4 extent B + 树的灵活管理,确保文件能够根据实际需求动态调整存储空间。
当文件需要扩展时,比如向文件中追加数据,ext4 文件系统首先会确定需要分配的新物理块数量。这一过程需要综合考虑多个因素,如文件系统的块大小、追加数据的大小以及当前文件的存储布局等。如果文件系统的块大小为 4KB,而需要追加的数据大小为 10KB,那么就需要分配至少 3 个新的物理块(10KB / 4KB 向上取整)。
确定好需要分配的物理块数量后,ext4 会调用 ext4_mb_new_blocks 函数从磁盘的空闲块中分配新的物理块。这个函数会根据文件系统的空闲块管理策略,选择合适的物理块分配给文件。在选择物理块时,它会优先考虑与文件现有数据块相邻的物理块,以提高数据的连续性和读写性能。如果文件当前的数据块集中在磁盘的某个区域,那么新分配的物理块也会尽量靠近这个区域,这样在后续的文件读写操作中,可以减少磁盘寻道时间,提高操作效率。
分配好新的物理块后,ext4 会创建新的 ext4_extent 结构来记录这些新分配的物理块与文件逻辑块的映射关系。新的 ext4_extent 结构会包含起始逻辑块地址、映射的连续物理块个数以及起始物理块地址等信息。假设新分配的物理块起始地址为 1000,连续分配了 3 个物理块,对应的逻辑块地址从文件当前的末尾开始,假设为 500,那么新创建的 ext4_extent 结构中,ee_block 为 500,ee_len 为 3,ee_start_lo 和 ee_start_hi 组合表示起始物理块地址 1000。
接着,ext4 会调用 ext4_ext_insert_extent 函数将新的 ext4_extent 结构插入到 ext4 extent B + 树中。在插入过程中,ext4_ext_insert_extent 函数会根据 B + 树的结构和算法,找到合适的位置插入新的 ext4_extent 结构。它会从根节点开始,通过比较新 ext4_extent 结构的起始逻辑块地址与节点中现有 ext4_extent_idx 或 ext4_extent 的起始逻辑块地址,确定插入的路径和位置。如果插入位置的节点已满,它会进行节点分裂操作,将节点中的部分 ext4_extent_idx 或 ext4_extent 移动到新创建的节点中,以保证 B + 树的平衡和一致性。在插入完成后,还会更新 B + 树的相关统计信息,如节点中的有效条目数、树的深度等,以确保 B + 树的结构正确和高效。
当文件需要收缩时,比如删除文件中的部分数据,ext4 会首先根据删除的数据范围,确定需要释放的物理块。这需要准确地解析文件的逻辑结构和 ext4 extent B + 树中的映射关系,找到与删除数据对应的物理块。假设要删除文件中从逻辑块地址 300 到 350 的数据,ext4 会通过 ext4 extent B + 树找到对应的 ext4_extent 结构,确定这些逻辑块对应的物理块范围。
确定好需要释放的物理块后,ext4 会调用相应的函数将这些物理块标记为空闲,并从 ext4 extent B + 树中删除对应的 ext4_extent 结构或调整其范围。如果删除的数据正好是一个完整的 ext4_extent 结构所映射的范围,那么直接从 B + 树中删除该 ext4_extent 结构即可。如果删除的数据只是 ext4_extent 结构所映射范围的一部分,那么需要调整该 ext4_extent 结构的 ee_len 和 ee_block 等成员,以反映剩余的映射关系。
在删除或调整 ext4_extent 结构后,ext4 还会检查 ext4 extent B + 树的结构,进行必要的合并操作。如果删除操作导致某个节点中的 ext4_extent_idx 或 ext4_extent 数量过少,可能会影响 B + 树的性能和空间利用率,此时 ext4 会尝试将该节点与相邻节点进行合并,以优化 B + 树的结构。在合并过程中,会重新调整节点中的 ext4_extent_idx 或 ext4_extent 的顺序和范围,确保 B + 树的有序性和正确性。
通过这样的方式,ext4 文件系统能够灵活地处理文件的扩展与收缩操作,高效地管理磁盘空间,保证文件系统的性能和稳定性。无论是文件的增长还是缩减,ext4 extent 机制和 ext4 extent B + 树都能够快速响应,为文件的存储和管理提供可靠的支持。
六、ext4 extent 与其他文件系统的对比优势
6.1与 ext2、ext3 对比
在 Linux 文件系统的发展历程中,ext2 和 ext3 曾经是广泛应用的文件系统,它们为 Linux 系统的文件存储和管理做出了重要贡献。然而,随着技术的不断进步和数据量的日益增长,ext2 和 ext3 在处理大文件时逐渐暴露出一些局限性。而 ext4 文件系统的出现,尤其是其引入的 extent 机制,在很大程度上解决了这些问题,展现出了显著的优势。
ext2 和 ext3 采用的是间接块映射方式。在这种方式下,当处理大文件时,需要建立大量的间接块映射表来记录文件逻辑块与物理块之间的映射关系。以一个 100MB 大小的文件为例,假设每个数据块大小为 4KB,那么在 ext2 和 ext3 中,就需要建立 25,600 个数据块的映射表。这不仅会占用大量的磁盘空间来存储这些映射表,导致元数据开销大幅增加,还会使得文件的寻址过程变得极为复杂。在读取文件时,系统需要多次读取间接块映射表,才能找到文件数据所在的物理块,这大大增加了磁盘 I/O 的次数,降低了文件的访问效率。
而 ext4 的 extent 机制则带来了全新的解决方案。extent 将文件的数据块组织成连续的块组,每个 extent 为一组连续的数据块。对于上述 100MB 大小的文件,ext4 可以通过一个或几个 extent 来表示,例如 “该文件数据保存在接下来的 25,600 个数据块中”。这样,文件的逻辑块与物理块之间的映射关系变得更加简洁和高效。通过 extent,系统可以直接定位到文件数据所在的连续物理块,减少了对间接块映射表的依赖,从而大大减少了元数据的开销。在读取文件时,系统只需通过 extent 结构中的信息,就可以快速找到文件数据的物理位置,提高了寻址效率,减少了磁盘 I/O 的次数,进而提升了文件的读写性能。
extent 机制还能有效减少文件碎片化。在 ext2 和 ext3 中,由于文件数据块的分配较为分散,随着文件的不断创建、删除和修改,磁盘上容易出现大量的碎片,这些碎片会导致文件的读写性能下降。而 ext4 的 extent 机制通过将文件数据块连续存储,减少了文件碎片化的程度,使得文件在磁盘上的存储更加紧凑和有序。这不仅有助于提高磁盘空间的利用率,还能进一步提升文件的读写性能,因为连续存储的数据块可以减少磁盘寻道时间,提高数据的读取速度。
6.2与其他现代文件系统对比
在现代文件系统的大家庭中,除了 ext4,还有 XFS、Btrfs 等优秀的文件系统,它们各自具有独特的特点和优势。与这些文件系统相比,ext4 extent 在性能、空间利用率、兼容性等方面也展现出了自己的特色。
在性能方面,ext4 extent 在处理顺序读写时表现出色。由于 extent 将文件数据块连续存储,在进行顺序读写操作时,磁盘可以连续地读取或写入数据,减少了寻道时间和旋转延迟,从而提高了读写速度。在处理大文件的顺序读取时,ext4 extent 能够快速地将数据传输到内存中,满足用户对大数据量快速读取的需求。而 XFS 在处理大文件时也有不错的性能表现,它采用了 B + 树和 Extent 来组织文件,在处理大文件的随机读写方面可能具有一定优势。Btrfs 则在一些高级功能上表现突出,但其性能在某些情况下可能不如 ext4 稳定。
在空间利用率上,ext4 extent 通过减少文件碎片化,有效地提高了磁盘空间的利用率。与一些文件系统相比,ext4 extent 能够更合理地分配磁盘空间,减少空闲块的浪费。Btrfs 虽然也采用了 extent 的概念来管理磁盘空间,但其元数据结构相对复杂,可能在一定程度上影响了空间利用率。
兼容性方面,ext4 作为 Linux 系统中广泛使用的文件系统,具有良好的兼容性。它可以在大多数 Linux 发行版上稳定运行,并且能够与其他 Linux 文件系统进行良好的交互。相比之下,XFS 和 Btrfs 在一些较旧的 Linux 发行版中可能需要额外的配置或支持。
ext4 extent 在与其他文件系统的对比中,凭借其在性能、空间利用率和兼容性等方面的优势,成为了 Linux 文件系统中的重要选择。它不仅能够满足用户对文件存储和管理的基本需求,还能在处理大文件和复杂应用场景时表现出卓越的性能,为 Linux 系统的稳定运行和高效数据处理提供了有力支持。
相关文章:
Linux内核源码:ext4 extent详解
在 Linux 系统的庞大体系中,文件系统就像是一个井然有序的图书馆,而 ext4 文件系统则是这座图书馆中极为重要的 “藏书室”,它负责高效管理和存储数据。在 ext4 众多的奥秘中,ext4 extent 犹如一颗璀璨的明珠,起着关键…...
Maven jar 包下载失败问题处理
Maven jar 包下载失败问题处理 1.配置好国内的Maven源2.重新下载3. 其他问题 1.配置好国内的Maven源 打开⾃⼰的 Idea 检测 Maven 的配置是否正确,正确的配置如下图所示: 检查项⼀共有两个: 确认右边的两个勾已经选中,如果没有请…...
自指学习:AGI的元认知突破
文章目录 引言:从模式识别到认知革命一、自指学习的理论框架1.1 自指系统的数学定义1.2 认知架构的三重反射1.3 与传统元学习的本质区别二、元认知突破的技术路径2.1 自指神经网络架构2.2 认知效能评价体系2.3 知识表示的革命三、实现突破的关键挑战3.1 认知闭环的稳定性3.2 计…...
排序算法--希尔排序
希尔排序是插入排序的改进版本,适合中等规模数据排序,性能优于简单插入排序。 // 希尔排序函数 void shellSort(int arr[], int n) {// 初始间隔(gap)为数组长度的一半,逐步缩小for (int gap n / 2; gap > 0; gap …...
Java 2024年面试总结(持续更新)
目录 最近趁着金三银四面了五六家公司吧,也整理了一些问题供大家参考一下(适合经验三年左右的)。 面试问题(答案是我自己总结的,不一定正确): 总结: 最近趁着金三银四面了五六家公…...
TensorFlow是个啥玩意?
TensorFlow是一个开源的机器学习框架,由Google开发。它可以帮助开发者构建和训练各种机器学习模型,包括神经网络和深度学习模型。TensorFlow的设计理念是使用数据流图来表示计算过程,其中节点表示数学运算,边表示数据流动。 Tens…...
不可信的搜索路径(CWE-426)
漏洞描述:程序使用关键资源时(如动态链接库、执行文件、配置文件等)没有明确的指定资源的路径,而是依赖操作系统去搜索资源,这种行为可能被攻击者利用,通过在搜索优先级较高的目录放置不良资源,…...
Linux——基础命令
$:普通用户 #:超级用户 cd 切换目录 cd 目录 (进入目录) cd ../ (返回上一级目录) cd ~ (切换到当前用户的家目录) cd - (返回上次目录) pwd 输出当前目…...
利用TensorFlow.js实现浏览器端机器学习:一个全面指南
引言 随着深度学习技术的不断发展,机器学习已从传统的服务器端运算逐渐转向了前端技术。TensorFlow.js 是 Google 推出的一个用于在浏览器中进行机器学习的开源库,它允许开发者在浏览器中直接运行机器学习模型,而无需依赖后端服务器。Tensor…...
利用HTML和css技术编写学校官网页面
目录 一,图例展示 二,代码说明 1,html部分: 【第一张图片】 【第二张图片】 【第三张图片】 2,css部分: 【第一张图片】 【第二张图片】 【第三张图片】 三,程序代码 一,…...
SpringSecurity密码编码器:使用BCrypt算法加密、自定义密码编码器
1、Spring Security 密码编码器 Spring Security 作为一个功能完备的安全性框架,一方面提供用于完成加密操作的 PasswordEncoder 组件,另一方面提供一个可以在应用程序中独立使用的密码模块。 1.1 PasswordEncoder 抽象接口 在 Spring Security 中,PasswordEncoder 接口代…...
笔记:新能源汽车零部件功率级测试怎么进行?
摘要:本文旨在梳理主机厂对新能源汽车核心零部件功率级测试需求,通过试验室的主流设备仪器集成,快速实现试验方案搭建,并体现测试测量方案的时效性、便捷性优势。目标是通过提升实现设备的有效集成能力、实现多设备测试过程的有效协同、流程化测试,可快速采集、分析当前数…...
ES6中的map和原生的对象有什么区别?
在 ES6 中,Map 和原生的对象(Object)都是用来存储键值对数据的集合,但它们有显著的区别。以下是它们之间的主要区别: 1. 键的类型 Object: 只允许使用字符串或符号作为键。其他类型的键(如数字或对象&…...
2502vim,vim文本对象中文文档
介绍 文本块用户(textobj-user)是一个可帮助你毫不费力地创建自己的文本对象的Vim插件. 因为有许多陷阱需要处理,很难创建文本对象.此插件隐藏了此类细节,并提供了声明式定义文本对象的方法. 你可用正则式来定义简单的文本对象,或使用函数来定义复杂的文本对象.如… 文本对…...
spring security与gateway结合进行网关鉴权和授权
在Spring Cloud Gateway中集成Spring Security 6以实现鉴权和认证工作,可以在网关代理层完成权限校验和认证。这种架构通常被称为“边缘安全”或“API网关安全”,它允许你在请求到达后端服务之前进行集中式的安全控制。 以下是如何配置Spring Cloud Gat…...
LabVIEW在电机自动化生产线中的实时数据采集与生产过程监控
在电机自动化生产线中,实时数据采集与生产过程监控是确保生产效率和产品质量的重要环节。LabVIEW作为一种强大的图形化编程平台,可以有效实现数据采集、实时监控和自动化控制。详细探讨如何利用LabVIEW实现这一目标,包括硬件选择、软件架构设…...
log4j2日志配置文件
log4j2配置文件每个项目都会用到,记录一个比较好用的配置文件,方便以后使用时调取,日志输出级别为debug,也可以修改 <?xml version"1.0" encoding"UTF-8"?> <Configuration monitorInterval"180" packages""><prope…...
用Deepseek做EXCLE文件对比
背景是我想对比两个PO系统里的一个消息映射,EDI接口的mapping有多复杂懂的都懂,它还不支持跨系统版本对比,所以我费半天劲装NWDS,导出MM到excle,然后问题来了,我需要对比两个excel文件里的内容,…...
Tailwind CSS v4.0 升级与 Astro 5.2 项目迁移记录
本文博客链接 https://ysx.cosine.ren/tailwind-update-v4-migrate 自用小记。 Tailwind CSS v4.0 - Tailwind CSS 新的高性能引擎 - 完整构建的速度速度快 5 倍,增量构建的速度快于 100 倍以上 —— 以微秒为单位进行测量。为现代 Web 设计 - 建立在前沿的 CSS 特…...
TongSearch3.0.4.0安装和使用指引(by lqw)
文章目录 安装准备手册说明支持的数据类型安装控制台安装单节点(如需集群请跳过这一节)解压和启动开启X-Pack Security和生成p12证书(之后配置内置密码和ssl要用到)配置内置用户密码配置ssl(先配置内置用户密码再配ssl)配置控制台…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
解析两阶段提交与三阶段提交的核心差异及MySQL实现方案
引言 在分布式系统的事务处理中,如何保障跨节点数据操作的一致性始终是核心挑战。经典的两阶段提交协议(2PC)通过准备阶段与提交阶段的协调机制,以同步决策模式确保事务原子性。其改进版本三阶段提交协议(3PC…...
WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
