将&符号应用于C / C ++或任何其他此类语言的变量或数据类型时返回的是什么类型的地址?

从我听说OS类中的虚拟和物理内存概念这一天起,这是一个非常基本的问题令人难以置信。 现在我知道在加载时和编译时,虚拟地址和逻辑地址绑定方案是相同的,但在执行时它们是不同的。

首先,为什么在编译和加载时生成虚拟地址以及在我们应用&号运算符来获取变量,天真数据类型,用户定义类型和函数定义地址的地址时返回什么是有益的?

操作系统如何完全从虚拟地址映射到物理地址? 这些问题都是出于好奇心而且我会喜欢考虑现代操作系统的一些好的和深刻的见解’,早期的操作系统是怎样的’。我只是特定于C / C ++,因为我对其他语言知之甚少。

物理地址发生在硬件中,而不是软件中。 可能/偶然的exception存在于操作系统内核中。 物理意味着它是系统总线和RAM芯片看到的地址。

物理地址不仅对软件无用,而且可能是一个安全问题。 能够访问任何物理内存而无需地址转换,并且知道其他进程的地址,将允许不受限制地访问机器。

也就是说,较小的或嵌入式计算机可能没有虚拟内存,而一些较旧的操作系统确实允许共享库指定其最终的物理内存位置。 这些政策损害了安全性并且已经过时。

在应用程序级别(例如Linux应用程序进程),仅存在虚拟地址。 局部变量位于堆栈(或寄存器)中。 堆栈以调用帧的forms组织。 编译器在当前调用帧内生成局部变量的偏移量,通常是相对于堆栈指针或帧指针寄存器的偏移量(因此局部变量的地址,例如在递归函数中,仅在运行时才知道)。

尝试在gdb调试器中逐步执行递归函数,并显示一些局部变量的地址以了解更多信息。 尝试gdbbt命令。

类型

 cat /proc/self/maps 

了解执行该cat命令的进程的地址空间(和虚拟内存映射)。

在内核中,从虚拟地址到物理RAM的映射是通过实现分页和驱动MMU的代码完成的。 某些系统调用(特别是mmap(2)和其他系统调用)可以更改进程的地址空间。

一些早期的计算机(例如20世纪50年代或1960年代早期的计算机,如CAB 500或IBM 1130或IBM 1620 )没有任何MMU,即使最初的Intel 8086也没有任何内存保护。 那时(1960年代), C不存在。 在没有MMU的处理器上,您没有虚拟地址(仅包括物理地址,包括洗衣机制造商的嵌入式C代码)。 有些机器可以通过物理交换机保护写入某些内存库。 今天,一些低端廉价处理器(洗衣机中的处理器)没有任何MMU。 大多数便宜的微控制器没有任何MMU。 通常(但不总是),程序在某些ROM中,因此不能被错误的代码覆盖。