当一个进程启动时,它会获得自己的虚拟地址空间。虚拟地址空间的大小取决于您的操作系统。通常,32 位进程获得 4 GiB(4 giga 二进制)地址,64 位进程获得 18 EiB(18 exa 二进制)地址。
您不能以任何方式访问未映射到虚拟地址空间的任何内容,因为根据定义,任何未映射到虚拟地址空间的内容都没有适合您的地址。您可能会尝试访问当前未映射到任何内容的虚拟地址空间区域,在这种情况下,您会遇到段错误异常。
在任何给定时间,并非所有地址空间都映射到某物。也不是所有的都可以映射(可以映射多少取决于处理器和操作系统)。在当前一代的英特尔处理器上,最多可以映射 256 TiB 的地址空间。请注意,操作系统可以进一步限制这一点。例如,对于 32 位进程(最多有 4 个 GiB 地址),Windows 默认为系统保留 2 GiB,为应用程序保留 2 GiB(但有一种方法可以为系统保留 1 GiB,为应用程序保留 3 GiB)。
应用程序运行时使用了多少地址空间以及映射了多少变化。操作系统特定的工具可以让您监控当前分配的内存和虚拟地址空间对于正在运行的应用程序是什么。
代码段、数据段、BSS 等是指链接器创建的可执行文件的不同区域的术语。通常,代码与静态不可变数据分开,静态不可变数据与静态分配但可变的数据分开。堆栈和堆与上述所有内容分开。它们的大小由编译器和链接器计算。请注意,每个二进制文件都有自己的部分,因此任何动态链接的库都将分别映射到地址空间中,每个库都将其自己的部分映射到某个地方。然而,堆和堆栈不是二进制映像的一部分,通常每个进程只有一个堆栈和一个堆。
堆栈的大小(至少是初始堆栈)通常是固定的。编译器和/或链接器通常有一些标志,可用于设置运行时所需的堆栈大小。堆栈通常“向后增长”,因为这就是处理器堆栈指令的工作方式。让堆栈沿一个方向增长,而其余的则沿另一个方向增长,这样在您希望两者都不受限制但又不知道每个可以增长多少的情况下,组织内存变得更容易。
通常,堆是指进程启动时未预先分配的任何东西。在最低级别,有几个与堆管理相关的逻辑操作(并非所有操作都像我在此处描述的那样在所有操作系统中实现)。
虽然地址空间是固定的,但一些操作系统会跟踪它的哪些部分当前被进程回收。即使不是这种情况,流程本身也需要对其进行跟踪。因此,最低级别的操作是实际决定要使用地址空间的某个区域。
第二个低级操作是指示操作系统将该区域映射到某物。这个一般可以
我可能忘记了其他组合,但这些是主要的。
当然,使用的总空间实际上取决于您如何定义它。当前使用的 RAM 与当前映射的地址空间不同。但正如我在上面所写的,依赖于操作系统的工具应该可以让您了解当前正在发生的事情。