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

时间:2017-10-11 08:10:46

标签: memory rust

我想用:

打印变量的内存位置(地址)
let x = 1;
println!("{:p}", &x);

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

我的电脑有16GB的RAM,为什么这么大的数字呢? x64架构是否使用大间隔序列而不是简单的1增量来访问内存位置?

在x86中,通常第一个位置从0开始,然后是1,2等,所以你可以拥有的最高数字大约为40亿,所以地址数总是等于或少于40亿。

为什么x64的情况不是这样?

2 个答案:

答案 0 :(得分:11)

您在此处看到的是virtual memory的效果。内存管理很难,当操作系统和数百个进程必须共享内存时,内存管理变得更加困难。为了处理这种巨大的复杂性,使用了虚拟内存的概念。我只是简单地解释一下这里的基础知识;这个话题要复杂得多,你也应该把它读到别的地方。

在大多数现代计算机上,每个进程都认为它拥有(几乎)完整的内存空间。但是进程从不处理物理地址,而是处理虚拟地址。每次进程实际从内存中读取时,这些虚拟地址都会映射到物理地址。地址的这种转换由所谓的MMU(存储器管理单元)完成。如何映射地址的规则由操作系统设置。

启动PC时,操作系统会创建初始映射。每次启动进程时,操作系统都会向进程添加几片物理内存并相应地修改映射。这样一来,这个过程就有了记忆力。

在x86_64上,地址空间为64位宽,因此每个进程都认为它拥有所有这些2 ^ 64个地址。当然不是这样:

  1. 世界上没有一台拥有那么多内存的PC。 (事实上​​,今天大多数CPU只能使用280 TB的RAM,因为它们内部只能使用48位来寻址物理内存。显然,即使这些280TB也足够了。)
  2. 即使你有那么多记忆,也有其他过程也会使用那段记忆。
  3. 那么当你试图读取一个没有映射的地址时会发生什么(在64位的地址中,绝大多数是地址)? MMU触发页面错误。这使CPU通知操作系统处理此问题。

      

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

    确实如此,但如果x86系统的RAM少于4GB,也是如此。虚拟内存已存在很长时间了。

    这就是为什么你会看到这么大的地址的简短摘要。请再次注意,我在这里隐藏了许多细节。

答案 1 :(得分:6)

您的程序使用的指针位于this.。 x86-64使用64位指针。这是AMD64的主要目标之一,同时添加了更多的整数和XMM寄存器。你是对的,i386只有32位指针,每个进程只能覆盖4GB的地址空间。

0x7fff51ef6380看起来像一个堆栈指针,我觉得这个代码很有意义。

virtual address space:当前的x86-64硬件只实现48位虚拟地址,这是阻止软件依赖它的机制。这样可以在将来扩展地址空间而不会破坏软件。

系统中的物理RAM量 nothing 与此无关。你会在x86-64系统上看到(大约)相同的数字,内存为128MB,+ / - 堆栈Linux on x86-64 (for example) puts the stack near the top of the lower canonical address range