为什么使用 {:p} 打印的内存地址比我的 RAM 规格要大很多?

9

我想使用以下代码打印变量的内存地址:

let x = 1;
println!("{:p}", &x);

这将打印十六进制值为0x7fff51ef6380,在十进制中为140734568031104

我的计算机有16GB的RAM,那么为什么会出现这么大的数字?x64架构是否使用了大间隔序列来访问内存位置,而不是简单的1增量?

在x86中,通常第一个位置从0开始,然后是1、2等,因此您可以拥有的最高数字约为40亿,所以地址号始终等于或小于40亿。

x64为什么不是这种情况呢?

2个回答

16
你在这里看到的是 虚拟内存 的效果。内存管理很难,当操作系统和成百上千的进程必须共享内存时,情况变得更加复杂。为了解决这个巨大的复杂性,使用了 虚拟内存 的概念。我将在此简要介绍基础知识;这个话题非常复杂,你也应该在其他地方阅读相关内容。
在大多数现代计算机上,每个进程都认为它(几乎)拥有完整的内存空间。但进程从不处理 物理地址,而是处理 虚拟地址。这些虚拟地址每次进程实际从内存中读取数据时都会被映射到物理地址上。这种地址转换由所谓的 MMU(内存管理单元)完成。如何映射地址的规则由操作系统设置。
当你启动计算机时,操作系统会创建一个初始映射。每次启动一个进程时,操作系统都会向该进程添加一些物理内存,并相应地修改映射。这样,进程就有可以运行的内存。
在 x86_64 上,地址空间最宽为64位,因此每个进程都认为自己拥有所有这 2^64 个地址。当然,这不是真的:
  1. 世界上没有一台计算机能够拥有那么多内存。(事实上,大多数 CPU 今天只能使用 280 TB 的 RAM,因为它们在寻址物理内存时只能使用 48 位。即使这 280TB 对现在来说也足够了。)
  2. 即使你拥有那么多内存,还有其他进程也会使用其中的一部分。
那么当你尝试读取未映射的地址(在64位系统中,这是大多数地址)时会发生什么?MMU 触发了一个页面错误。这使 CPU 通知操作系统进行处理。

我的意思是,在x86中,通常第一个位置从0开始,然后是1、2等等,所以你可以拥有的最高数字约为40亿。

虽然如此,如果您的x86系统内存少于4GB,这也是正确的。虚拟内存已经存在了相当长的时间。


这就是为什么您会看到如此大的地址的简短总结。请注意,我在这里忽略了许多细节。


@PeterCordes 关于第二点:我是指你所说的(我甚至在上面提到过这个优点),但现在我意识到我写的方式容易引起误解。对此我表示抱歉,我会尽快修复它。谢谢! - Lukas Kalbertodt
嘿,我在评论之前只是粗略地浏览了一下,不知道你是否指的是“效果”这个词。 - Peter Cordes
1
小问题:现代CPU核心没有单独的“MMU”。虚拟内存支持完全嵌入到每个CPU核心中,TLB与一级缓存交织在一起。x86有专用的页表遍历硬件,因此操作系统所要做的就是将页目录指针放入CR3中,或修改内存中的现有页表并使任何受影响的转换无效。 - Peter Cordes
我知道谈论“MMU”对于初学者来说是一个有用的心理模型,但是人们会想知道“每个核心是否有自己的MMU”... 我想我只是想抱怨一下我的小烦恼,而不是让你真正改变你的答案。 :P 但实际上,“MMU”功能被分成了iTLB(与L1I缓存耦合)、dTLB(与L1D缓存耦合)、第二级TLB来服务于来自L1TLB的TLB缺失,以及页行走硬件来服务于L2 TLB缺失。还有CR3控制寄存器... - Peter Cordes
@JohnSmith:接近了,但物理地址空间不包括交换文件。它们没有与内存总线物理连接!您可以将文件映射到虚拟地址空间中,如果它们尚未被映射,则会在需要时将其故障转移到物理页面上。这可能需要清除其他物理页面以腾出空间。(因此,返回并访问您之前触摸过的虚拟页面可能会再次故障。) - Peter Cordes
显示剩余3条评论

8
你的程序使用的指针位于虚拟地址空间中。x86-64使用64位指针。这是AMD64的主要目标之一,同时还增加了更多的整数和XMM寄存器。你说得对,i386只有32位指针,每个进程只能覆盖4GB的地址空间。 0x7fff51ef6380看起来像是堆栈指针,我猜这对那段代码来说是有意义的。 例如,在x86-64上运行Linux将堆栈放置在较低的规范地址范围的顶部:当前的x86-64硬件仅实现48位虚拟地址,这是防止软件依赖它的机制。这允许在未来扩展地址空间而不破坏软件。

您系统中的物理RAM数量与此无关。在具有128MB RAM的x86-64系统上,您会看到(大约)相同的数字,+/-堆栈 地址空间布局随机化(ASLR)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接