Linux内核如何在64位系统上初始化mem_map数组?

Linux内核如何在64位系统上初始化mem_map数组?

我知道 Linux 内核借助 C 结构来跟踪每个物理页帧的状态struct page。所有页框的结构形成一个mem_map[]类型数组struct page,以便您可以使用页框编号作为索引轻松检索特定页框的结构。在具有 4 GiB 物理内存的 x86 32 位系统上,该数组由 2 20
个条目 组成,因为页面大小为 4096 字节,每个条目大小为 32 字节,因此整个数组消耗 32 MiB。现在,当我将其传输到具有例如 4 TiB 物理内存的 x86 64 位系统时,该数组由 2 30 个条目 组成,每个条目大小为 32 字节,因此该数组消耗 32 GiB。当然,随着物理内存的增加,如果达到 4 PiB(在 amd64 架构上为2 52字节)的平台特定限制,阵列可以增加到最大 32 TiB。 内核是否真的必须在启动时初始化那么多数据,还是我错过了什么?

答案1

有三种不同的物理内存模型Linux 内核使用的:您描述的平面模型、不连续内存模型和稀疏内存模型。

Linux 支持的大多数(如果不是全部)64 位架构默认使用后者。它依赖于内存部分以及大多数架构上虚拟分配的内存映射。代表实际存在的物理内存所需的条目根据需要进行分配和初始化。在大型系统上,甚至可以推迟此初始化,这样就不会延迟启动。

答案2

https://lwn.net/Articles/839737/(12/11/2020) 仍然说“页面结构通常占用可用内存的 1.5% 以上”。我认为百分比来自 64/4096 = 1.5625%。

在我的具有 5700 GB 内存并在 Azure 上运行的 M416s_v2 Ubuntu 20.04 VM 中,开销为 1.5657%,接近 1.5625%:

“cat /proc/meminfo |grep MemTotal:”显示:“MemTotal: 5882783592 kB”

(我为Linux kdump保留512MB内存):“cat /proc/cmdline”显示“BOOT_IMAGE=/boot/vmlinuz-5.4.0-1010-azure root=PARTUUID=7327629e-2b41-4f48-893e-9ae930552551 ro console=tty1控制台=ttyS0 Earlyprintk=ttyS0 crashkernel=512M 恐慌=-1"

1 - (5882783592 / (5700.0 * 1024 *1024 - 512 * 1024)) = 0.015657580372575808

(5700 * 1024 * 1024) * (0.015657580372575808 - 64.0/4096) / 1024 = 190.16511865047505

除了页面结构之外,内核/驱动程序代码/数据/BSS 使用大约 190 MB。这里我们忽略固件保留的内存。

相关内容