为什么Linux(x86)的页面大小是4KB,如何计算?
- 2024-11-13 08:36:00
- admin 原创
- 24
问题描述:
x86架构上的Linux内核默认的内存页面大小是4KB,请问这个是怎么计算的,为什么呢?
解决方案 1:
默认页面大小由 CPU 的 MMU(内存管理单元)支持的大小决定。在 32 位保护模式下,x86 支持两种类型的页面:
正常的,4 KiB
巨大的,4 MiB
并非所有 x86 处理器都支持大页面。需要具有页面大小扩展 (PSE) 功能的 CPU。这不包括 Pentium 之前的处理器。几乎所有当前一代 x86 CPU 都实现了此功能。
4 KiB 也是其他架构中广泛使用的页面粒度。有人可能会认为,这个大小来自于将 32 位虚拟地址划分为页面目录/表中的两个 10 位索引,其余 12 位给出了 4 KiB 页面大小。
解决方案 2:
介绍
支持分页虚拟内存技术的首款 Intel 处理器是Intel 80386。该处理器支持单一页面大小,即 4 KB。由于它是在 1985 年发布的,因此我们必须回到那个时期才能理解 Intel 选择该特定页面大小的原因。
Atlas是第一台支持分页的计算机,页面大小为 3 KB,它对虚拟内存的设计产生了深远的影响,并激发了相关研究。该系统设计于 1958-1962 年间。值得注意的是,80386 支持的页面大小与 Atlas 支持的页面大小有些接近,尽管 80386 是在大约 20 年后设计的,而计算机(及其运行的工作负载)在那段时间内发生了根本性的变化!事实上,那个时期的许多计算机使用的页面大小在 0.5-5 KB 之间。当时的研究人员实际上花费了大量精力研究虚拟内存系统(分页和分段)。
一个大问题是:最佳页面大小是多少?20 世纪 60 年代和 70 年代发表了大量研究成果,试图研究和了解页面大小对应用程序性能的影响,并就如何选择页面大小提出建议或提供指导。当然,还有很多论文从未发表过。据我所知,其中包括英特尔的一份文件,上面写着“...因此,页面大小应该是 4 KB”。但影响或与页面大小交互的因素以及选择页面大小(或多个页面大小)的过程是众所周知的,这也是我将在本回答中从基本层面讨论的内容。我还将特别解释为什么 4 KB 的页面大小是合理的。
页面大小问题
在分页方法中,物理内存被组织为一系列连续的内存区域,这些区域称为页框,大小相同(这是分页的定义特征1)。每个页框都可以映射到虚拟地址空间中大小相等的块,称为虚拟页面。
假设一个页面由N
字节2组成(这意味着根据定义,页框的N
大小也是字节),并考虑由P
页面组成的虚拟地址空间(即,页码为 {0, 1, 2, ..., P
- 1} ,虚拟地址总数为N
P
)。还假设物理地址空间由F
页框组成(即,页框编号为 {0, 1, 2, ..., F
- 1} ,物理地址总数为N
F
)。
给定一个虚拟地址,需要VA
一种机制(映射设备PA
)来确定它被映射到的物理地址,或者如果未映射则应引发页面错误。映射设备使用存储在某处的数据结构(页表)来执行映射。该表中应该为每个分配的虚拟页面都有一个条目,描述页面的映射方式以及可能的一些附加属性(例如保护属性)。如您所见,页表条目的设计与页面大小相互作用。稍后我将讨论 Intel 80386 中页表条目的设计。
虚拟地址的大小为 log 2 ( N
P
),物理地址的大小为 log 2 ( N
F
)。的某些位VA
表示页面内的偏移量,而其他位表示页码,该页码使用映射设备来标识页面。
对于页面大小,我们有多少种选择?好吧,它可以最小为一个字节,最大为N
P
或N
F
,以较小者为准。选择很多。
页面大小最好是 2 的幂
虚拟地址VA
相当于一对页码和偏移量(PN
,OFF
)。转换过程应尽可能高效。对于程序员3来说,让页面内的字节在地址空间中连续会很方便。这样,多字节数据结构中项目的地址可以通过对单个地址进行简单的算术计算来计算,这将构成数据结构的基址。这可以通过使用虚拟地址的最低有效 log 2 ( N
) 位(向上舍入)来表示偏移量,并使用其余位来表示页码来实现。
如果N
不是 2 的幂,则偏移量和页码之间会有一些共享的位,具体取决于这些位的值。如果设为N
2 的幂,就不会出现这种复杂性。因此,使用 2 的幂的页面大小会很不错。所有支持分页的实际处理器都使用 2 的幂的页面大小(尽管寻址单位可能不是 8 位),这是有道理的。但说实话,目前还不清楚这是否真的很重要。使用当今的技术,是否N
是 2 的幂可能不会对性能或任何其他感兴趣的指标产生任何可衡量的影响。事实上,在未来,随着对越来越大的页面大小的需求,可能会出现一些不是 2 的幂的页面大小更好的情况。但到目前为止,这种情况还没有发生。我在这里要说明的观点是,不应自动忽略将页面大小设为非 2 的幂的设计选项。我相信这是研究未来虚拟内存系统的好机会。
无论如何,请记住,4 KB 页面的选择是在 80 年代做出的,页面大小的这种极小的变化(无论是理论上还是实验上)都表明并不重要。因此,2 的幂页面大小的便利性占了上风。这成倍减少了要考虑的页面大小数量。但我们仍然有很多选择。
青睐较小的页面尺寸
由于映射设备在页面级别工作,因此从操作系统的角度来看,分配单位是虚拟页面4。即使应用程序只需要分配 1 个字节,它仍然必须告诉操作系统为该 1 个字节分配整个虚拟页面。此问题称为内部碎片。每个应用程序(或甚至应用程序的每个组件)都有自己的虚拟地址空间,它从中以页面大小的块分配内存。每个应用程序都不应将单个页面用于其分配的单个对象,而是在分配更多页面之前从同一页面分配尽可能多的对象。但是,由于页面属性在页面级别工作,同一个应用程序可能使用多个用户模式内存管理器(例如使用多个 C/C++ 运行时时),并且应用程序很难与其他应用程序共享它们未使用的页面部分,因此系统中的许多页面可能会出现内部碎片。使用较小的页面大小可以帮助减少浪费的物理(整个系统)和虚拟(每个进程)内存量。
此外,应用程序在其整个生命周期中通常会经历多个阶段,它们在不同阶段表现出不同的内存需求。如果页面大小为 16 KB,但许多应用程序在其许多阶段可能只需要不到 10 KB,那么就会浪费大量物理内存,这可能会导致内存不足的情况,如果支持较小的页面大小(例如 8 KB 或 4 KB),这种情况本可以避免。
较小的页面大小更适合处理写时复制软页面错误,因为页面越小,创建副本所需的时间就越短。对于非常小的页面大小,这可能不会产生任何可测量的差异,具体取决于内存总线带宽。
70 年代计算机中可用的物理内存量通常为 10 或 100 KB。页面大小为数百 KB 或更大是没有意义的。事实上,当时应用程序的工作集通常只有几 KB 或几十 KB。因此,即使页面大小小到 16 KB 也不太可能实用,因为只有几个页面就可能消耗所有可用的物理内存。页面大小应与物理内存量一致。当然,这个论点可以应用于当今的系统(例如,拥有 128 GB 的页面是没有意义的)。
因此,考虑到70 年代和 80 年代初期的工作集大小和物理内存可用性,页面大小应为 2 的幂,范围为 2 0 -2 14。太棒了,现在我们只有 15 个选项可供选择。
青睐更大的页面尺寸
我们也可以认为页面大小越大越好。对于相同的工作集,较小的页面大小意味着每个应用程序需要更多的页面,这就需要页表条目来实现转换。这从根本上需要更大的页表,而不管页表的结构如何(尽管确切的开销取决于页表条目本身的设计,我将在后面讨论)。想象一下,例如,有 4 字节的页面和数十 KB 的典型工作集。那么,大多数物理内存实际上将被分配用于保存页表,而不是数据。将页表分页到辅助存储会导致单个内存引用的双页面错误,这对性能来说绝对是可怕的。这样的设计显然是荒谬的。
本质上,页面大小不应(大大)小于可能出现的最小工作集大小。这立即排除了大小为 2 0 -2 6的页面,只剩下 8 个选项。70 年代和 80 年代早期研究页面大小的论文大多只研究这 8 个选项。
还有一个原因使得较大的页面大小更具优势。虚拟内存的优点之一是能够透明地使用除主内存之外的辅助存储来保存易失性数据。但是,辅助存储设备是机械的,在批量传输时性能最佳。这实际上更像是一个指导方针,我们不应该排除任何页面大小。有不同设计和特性的设备,最终,批量传输的性能优势将在某个时候饱和。但在衡量页面大小对性能的影响时,这肯定是需要考虑的因素。如果所考虑的应用程序类型表现出很少的空间局部性,那么较小的页面大小仍然是可取的,因为将额外的字节复制到磁盘或从磁盘复制出来并不是完全免费的。
引用的空间局部性鼓励使用某些页面大小。对于非常小的页面大小,页面中的所有字节很可能会在很短的时间内被使用。随着页面大小的增大,不太可能使用的字节数会增加。但是,对于非常大的页面,所有工作集可能都适合少量页面,而与局部性无关。因此,为了最大限度地减少页面错误的数量,页面大小应该太小或太大,但不能介于两者之间。但最终,这因应用程序而异。新兴的编程范式(例如面向对象编程和函数式编程)以及多线程等技术实际上可能会减少空间局部性,这是由于广泛使用链接结构以及不同应用程序相互交互的方式。更大的页面大小更有利于减少页面错误的数量。但是,对于多个应用程序之间共享的内存,较小的页面大小可能更适合,以减少共享页面的内部碎片。实验还表明,主存储器中可保存的页框数量与页面错误数量相关,有利于较小的页面大小。
当时,TLB 的必要性得到了广泛认可。英特尔在其专利中将其称为页面缓存(不确定英特尔是否是第一个使用这个术语的人)。快速 TLB 非常重要,因为地址转换是执行指令的关键路径。为了使它们尽可能快,它们应该做得很小,但它们只能缓存少量的页表条目。这促使人们使用更大的页面大小。
在寻找最佳页面大小的过程中,我们发现并不存在最佳页面大小。当时人们就知道需要支持多种页面大小。事实上,1965 年设计的 Multics 系统支持 64 或 1,024 字页面(一个字的大小为 36 位)。在不同情况下,2 7 -2 14范围内的页面大小在经验和理论上均被证明是最佳的。英特尔肯定已经观察到,4 KB 页面为其客户在 80 年代使用的应用程序带来了最佳平均性能。对于今天的计算机和应用程序来说,页面大小的这种微小差异并不像 70 年代和 80 年代那样产生太大影响。
Intel 80386页表项的设计
页目录条目和页表条目的设计在英特尔专利中有详细讨论。这很重要,因为页表条目的大小和页表的整体结构在许多关于页面大小的研究中都被考虑在内,因为它们都相互影响。为了简短回答,我不想更详细地讨论这个问题。
不久的将来的页面大小
几个月前,英特尔获得了一项专利,该专利显然提出了一个默认页面大小为 64 KB 的系统,但同时支持 4 KB 页面(和其他 IA-32e 页面大小)以实现向后兼容。我引用专利中的一段话:
由于支持将 64 KB 页面映射到 4 KB 子页面,VA64 直接支持当前定义的所有 4 KB 页面操作,包括每个 4 KB 页面的独立保护位和任意 4 KB 对齐地址映射。VA64 还支持 4 KB 边界上的 OS 内核页面管理,即使 OS 内核以 64 KB 为单位分配内存也是如此。由于支持大页面,VA64 支持现有分页系统(例如 Intel Corporation 的 IA-32e 分页系统)支持的虚拟地址范围的所有页面划分。因此,VA64 支持使用 4 KB 页面 Windows® OS 内核的应用程序和硬件设备,同时在可以使用 64 KB 页面时充分利用 64 KB 页面。
操作系统内核可以逐步采用 VA64 的功能,而不必要求第一代支持 VA64 的操作系统内核支持所有这些功能。例如,支持 VA64 的操作系统内核可以先将所有页面映射到当前大小(例如,英特尔公司的 IA-32e 分页系统中的 4 KB/2 GB/1 TB),但更改为新的页表格式。更改页表格式后,可以修改操作系统内核以将虚拟内存映射到 64 KB 单元,并更改为将 64 KB 页面存储在其空闲列表中。然后,只要对齐和保护允许,操作系统内核就可以开始使用 64 KB 页面,并添加对其他 VA64 功能的支持。
除了专利中写的内容外,我对 VA64 分页系统一无所知。互联网上没有关于它的任何地方。我想我们很快就会发现更多。
参考文献
Denning, PJ (1970)。虚拟内存。ACM 计算调查第 2 卷第 3 期,153-189。
Gelenbe, E.、Tiberio, P. 和 Boekhorst, JCA (1973)。请求调页系统中的页面大小。信息学报,3(1),1-23。
Alanko, TO,Verkamo, AI (1983)。虚拟内存中的分段、分页和最佳页面大小。性能评估,3(1),13-33。
Corbató, FJ 和 Vyssotsky, VA (1965)。Multics系统简介和概述。1965 年 11 月 30 日至 12 月 1 日秋季联合计算机会议论文集,第一部分(第 185-196 页)。
脚注
(1) 实际上,单个虚拟页面的大小可以是页框大小的倍数,但我们不去管这个。
(2)我们可以概括该公式,并使用术语“字”来指代内存的最小可寻址单元,而不是字节,但这并不重要。
(3) 可能不是程序员,这取决于编程语言,而是编译器、链接器、汇编器和处理二进制代码的工具。
(4) 当然可以设计一个支持同时使用分页和非分页的系统,从而可能支持多个分配单元,但我们不要这么做。
解决方案 3:
32位架构的4KB正常页面大小的设计其实很有趣:)
我想添加一个额外的答案来解释为什么它是合理的。
x86 使用“2 级页表”将虚拟内存地址转换为物理内存地址。
因此假设页目录和页表都包含 2 x个条目,页面大小为 2 y字节。为了充分利用 2 32 个地址,我们有:
2 x × 2 x × 2 y = 2 32 ⇒ 2x + y = 32
页目录/表中的每个条目占用 4 个字节(32 位),因此:
2 y / 4 = 2 x ⇒ y - 2 = x
因此 y = 12,页面大小(以字节为单位)为 2 y = 2 12 = 4KB。
那么“1 级页表”又如何呢?这很有趣,因为从逻辑上讲我们可以使用单个页表进行地址查找。
假设页目录包含 2 x 个条目,每个条目将一个地址映射到相应的页面,页面大小为 2 y字节。
同样,为了充分利用 2 的 32 个地址,我们需要:
2 x × 2 y = 2 32 ⇒ x + y = 32
和:
2 y / 4 = 2 x ⇒ y - 2 = x
我们得到 y = 17,页面大小为 2 y = 2 17 = 128KB。
我们可能还会争辩说,在“2 级页表”版本中,页目录和页表的大小可能不同。但是,这意味着我们将使用更大的页目录,它将占用多个内存页面。遗憾的是,每次生成新的用户进程时,对于其自己的页目录,操作系统都必须分配连续的页面,这在设计上并不优雅。
解决方案 4:
这取决于处理器架构。
在许多架构中,默认页面大小为 4 KB。通常可以通过切换到大页面模式来增加页面大小(有时会增加很多,例如 AMD64 的 1 GB)。这允许页表更小,从而可以提高性能。
解决方案 5:
我从维基百科文章中得到这个并引用:
页面大小通常由处理器架构决定
请查看以下文章:
http://en.wikipedia.org/wiki/Page_(computer_memory)
解决方案 6:
我添加这个答案/评论是因为睡眠排序的计算非常有趣,我必须将其添加到我的网页中(当然要注明来源)。
关于如何以编程方式计算页面大小的问题,可以在此处找到(可能的)答案。 sleepsort 提到的计算方式非常有趣。我对 x86_64 做了同样的事情,但结果并不像我预期的那样。
然而,进一步阅读内存管理 x86_64后,我发现对于 64 位英特尔,16 位未被使用,而是留下 48 位供我们计算。
9 位表示记忆树的分支,
每个分支又有 9 位,
这里又有 9 位表示分支
,最后 9 位表示最后一个分支的叶子
因此,内存页中每个地址有 48 - 36 = 12 位。2 12 = 4096,就像 sleepsort 之前提到的那样。
我只是想知道这个架构通过了多少次,3 还是 4(如果有人可以解释的话)
按照 sleepsort 的计算:
2 x 2 x 2 x 2 x 2 y = 2 48
4x + y = 48
这次每个地址有 8 个字节(8 字节 * 8 位/字节 = 64 位)
2 y / 2 3 = 2 x
y-3 = x
填写上面的等式:
4(y - 3) + y = 48
4y - 12 + y = 48
5y = 60
y = 12
因为 2 y代表页面大小,所以大小 = 2 12 = 4096 字节
让我问一下“Linux 中的那些大页面怎么办?”
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件