简体   繁体   English

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

[英]Why is the memory address printed with {:p} much bigger than my RAM specs?

I want to print the memory location (address) of a variable with: 我想打印变量的内存位置(地址):

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

This prints the hex value 0x7fff51ef6380 which in decimal is 140734568031104 . 这将打印十六进制值0x7fff51ef6380 ,十进制为140734568031104

My computer has 16GB of RAM, so why this huge number? 我的电脑有16GB的RAM,为什么这么大的数字呢? Does the x64 architecture use a big interval sequence instead of just simple 1 increment for accessing memory location? x64架构是否使用大间隔序列而不是简单的1增量来访问内存位置?

In x86, usually the first location starts at 0, then 1, 2, etc. so the highest number you can have is around 4 billion, so the address number was always equals or less than 4 billion. 在x86中,通常第一个位置从0开始,然后是1,2,等等。因此,您可以拥有的最高数字大约为40亿,因此地址编号始终等于或小于40亿。

Why is this not the case with x64? 为什么x64不是这种情况?

What you see here is an effect of virtual memory . 你在这里看到的是虚拟内存的影响。 Memory management is hard and it becomes even harder when the operating system and tens of hundreds of processes have to share the memory. 内存管理很难,当操作系统和数百个进程必须共享内存时,内存管理变得更加困难。 In order to handle this huge complexity, the concept of virtual memory was used. 为了处理这种巨大的复杂性,使用了虚拟内存的概念。 I'll just briefly explain the basics here; 我将简要介绍一下这里的基础知识; the topic is far more complex and you should read about it somewhere else, too. 这个话题要复杂得多,你也应该把它读到别的地方。

On most modern computers, each process thinks that it owns (almost) the complete memory space. 在大多数现代计算机上,每个进程都认为它拥有(几乎)完整的内存空间。 But processes never deal with physical addresses, but with virtual ones. 但是进程从不处理物理地址,而是处理虚拟地址。 These virtual addresses are mapped to physical ones each time the process actually reads from memory. 每次进程实际从内存中读取时,这些虚拟地址都会映射到物理地址。 This translation of addresses is done by the so called MMU (memory management unit). 地址的这种转换由所谓的MMU(存储器管理单元)完成。 The rules for how to map the addresses are setup by the operating system. 如何映射地址的规则由操作系统设置。

When you boot your PC, the operating system creates an initial mapping. 启动PC时,操作系统会创建初始映射。 Every time you start a process, the operating system adds a few slices of physical memory to the process and modifies the mapping appropriately. 每次启动进程时,操作系统都会向进程添加几片物理内存并相应地修改映射。 That way, the process has memory to play with. 这样,这个过程就有了记忆。

On x86_64, the address space is 64 bit wide, so each process thinks it owns all of those 2^64 addresses. 在x86_64上,地址空间为64位宽,因此每个进程都认为它拥有所有这些2 ^ 64个地址。 This is not true, of course: 当然,这不是真的:

  1. There isn't a single PC on the world with that much memory. 世界上没有一台拥有那么多内存的PC。 (In fact, most CPUs today can merely use 280 TB of RAM, since they internally can only use 48bit for addressing physical memory. And even these 280TB are enough for now, apparently.) (事实上​​,今天大多数CPU 只能使用280 TB的RAM,因为它们内部只能使用48位来寻址物理内存。显然,即使这些280TB也足够了。)
  2. Even if you had that much memory, there are other processes which use part of that memory, too. 即使你有那么多内存,也有其他进程使用那部分内存。

So what happens when you try to read an address which isn't mapped (which in 64bit land, are the vast majority of the addresses)? 那么当你尝试读取未映射的地址时会发生什么(在64位的地址中,绝大多数是地址)? The MMU triggers a page fault. MMU触发页面错误。 This makes the CPU notify the operating system to handle this. 这使CPU通知操作系统处理此问题。

What I mean is that in x86, usually first location starts at 0, then 1, 2, etc. so the highest number you can have is around 4 billion. 我的意思是在x86中,通常第一个位置从0开始,然后是1,2,等等,所以你可以拥有的最高数字大约是40亿。

That is true, but it is also true if your x86 system has less than 4GB of RAM. 这是事实,但如果您的x86系统的RAM少于4GB,也是如此。 Virtual memory exists for quite some time already. 虚拟内存已存在很长时间了。


So that's a short summary of why you see such big addresses. 这就是为什么你看到这么大的地址的简短摘要。 Again, please note that I glossed over many details here. 请再次注意,我在这里隐藏了许多细节。

The pointers your program works with are in virtual address space . 程序使用的指针位于虚拟地址空间中 x86-64 uses 64-bit pointers. x86-64使用64位指针。 This was one of the major goals of AMD64, along with adding more integer and XMM registers. 这是AMD64的主要目标之一,同时添加了更多的整数和XMM寄存器。 You are correct that i386 only has 32-bit pointers which only cover 4GB of address space in each process. 你是对的,i386只有32位指针,每个进程只能覆盖4GB的地址空间。

0x7fff51ef6380 looks like a stack pointer, which I guess makes sense for that code. 0x7fff51ef6380看起来像一个堆栈指针,我猜这个代码是有道理的。

Linux on x86-64 (for example) puts the stack near the top of the lower canonical address range : current x86-64 hardware only implements 48-bit virtual addresses and this is the mechanism to prevent software from depending on it. Linux on x86-64(例如)将堆栈置于较低规范地址范围的顶部 :当前x86-64硬件仅实现48位虚拟地址,这是防止软件依赖它的机制。 This allows the address space to be extended in the future without breaking software. 这允许将来扩展地址空间而不破坏软件。

The amount of phyiscal RAM in your system has nothing to do with this. 系统中的物理RAM量与此无关 You'd see (approximately) the same number on an x86-64 system with 128MB of RAM, +/- stack address space layout randomization (ASLR) . 你会在x86-64系统上看到(大约)相同的数字,内存为128MB,+ / - 堆栈地址空间布局随机化(ASLR)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM