在应用程序级别(例如 Linux 应用程序进程),仅存在虚拟地址。局部变量在堆栈上(或在寄存器中)。堆栈按调用框架组织。编译器在当前调用帧内生成局部变量的偏移量,通常是相对于堆栈指针或帧指针寄存器的偏移量(因此,局部变量的地址,例如在递归函数中,仅在运行时才知道)。
尝试在调试器中逐步执行递归函数gdb
并显示一些局部变量的地址以了解更多信息。也试试bt
.gdb
类型
cat /proc/self/maps
了解执行该命令的进程的地址空间(和虚拟内存映射)。cat
在内核中,从虚拟地址到物理 RAM 的映射是通过实现分页和驱动MMU的代码完成的。一些系统调用(尤其是mmap(2)和其他)可以更改进程的地址空间。
一些早期的计算机(例如 1950 年代或 1960 年代早期的计算机,如CAB 500或IBM 1130或IBM 1620)没有任何 MMU,甚至最初的Intel 8086也没有任何内存保护。那时(1960-s),C还不存在。在没有 MMU 的处理器上,您没有虚拟地址(只有物理地址,包括洗衣机制造商的嵌入式 C 代码)。有些机器可以通过物理开关保护对某些内存库的写入。今天,一些低端廉价处理器(洗衣机中的处理器)没有任何 MMU。大多数便宜的微控制器没有任何 MMU。通常(但并非总是),程序位于某些 ROM 中,因此不能被错误代码覆盖。