【问题标题】:i386 C process - What happens in the remaining 1 GB of addressable space?i386 C 进程 - 在剩余的 1 GB 可寻址空间中会发生什么?
【发布时间】:2023-04-04 23:18:01
【问题描述】:

据记载,在堆上分配的变量存储在低地址区域并朝着堆栈增长,反之亦然。我决定测试一下:

#include <stdio.h>
#include <stdlib.h>

const char my_const_global_var = '0';
char my_global_var = '0';

int main(void) {
    char my_stack_var = '0';
    char* my_heap_var = (char*) malloc(1);
    *my_heap_var = '0';
}

似乎my_const_global_varmy_global_var 是在低地址区域中寻址的(在000XXXXX 之后和堆之前不久),但令我惊讶的是my_stack_var 的地址是完全正确大约 75% 标记(大约 bffbdaXX)。我猜当我的全局/堆/堆栈变量超过 3 GB 内存时我会得到一个段错误,所以我进行了搜索,发现提到了 a 3 GB barrier 但没有提及在剩余的 1 GB 可寻址空间中发生了什么。

剩余 25% 的内存地址空间会发生什么?

【问题讨论】:

  • 在 32 位系统中只有 3.5 GB 是可寻址的(没有 PAE)。据推测,您看到的不可寻址的 512 MB 是为操作系统保留的。 Linux/Unix 系统为 root 保留 10% 的资源。
  • 取决于平台。 Linux 和 Windows 使用不同的方法(Windows 是可配置的)。还取决于主机操作系统 - 32 位操作系统上的 32 位进程可以获得一种行为,而在 64 位操作系统上运行的 32 位进程可以获得不同的行为。
  • @ElliottFrisch 3.5GB 不是标准的用户模式/内核模式拆分。您可能会想到这样一个事实,即 32 位操作系统在没有 PAE 的情况下无法使用完整的 4GB 物理 RAM(由于内存映射设备占用了一些物理地址空间),但这不是这个问题的意义所在 - 并且数量取决于给定系统中安装的特定设备。它不固定为 3.5GB。
  • @AndrewMedico 是的,我正在考虑从 4gb 堆栈的顶部向后映射视频内存。

标签: c memory heap-memory stack-memory


【解决方案1】:

在 32 位 x86 CPU 上运行的保护模式操作系统通常将 32 位虚拟地址空间分为两个主要区域。第一个用于用户进程,第二个用于内核。虚拟地址空间不直接寻址物理内存。相反,它通过内核维护的页表映射到物理内存。这允许操作系统为每个进程提供自己的虚拟地址空间,从而将它们彼此隔离。当它切换进程时,它会更改页表,以便虚拟地址空间的用户区指向新进程使用的物理内存位置。

但是,当它切换进程时,操作系统不会更改对应于内核区域的页表条目。这意味着虽然每个进程都有自己的物理内存映射到用户区域,但每个进程的内核区域保持不变。将内核内存映射到每个进程的虚拟地址空间可以在执行系统调用时更快地从用户模式转换到内核模式。如果内核没有映射到每个进程,操作系统本质上必须切换进程(到假设的内核“进程”)来执行系统调用。与仅从用户模式转换到内核模式相比,切换进程的成本要高得多。

大多数 64 位 x86 操作系统也有类似的拆分,但由于它们具有更大的虚拟地址空间,它们将虚拟地址空间划分为更大的块。在运行 32 位程序时,这些操作系统通常允许程序访问全部或几乎全部的前 4 GB 虚拟地址空间。

请注意,虚拟内存如何划分为用户和内核区域不受系统中物理内存量的影响。除非明确配置不同,否则只有 64 MB RAM 的机器在运行完全相同的操作系统时将具有与具有 64 GB 内存的机器相同的用户/内核虚拟地址空间拆分。

【讨论】:

  • 在 64 位 Windows 上,如果与 /LARGEADDRESSAWARE 选项链接,32 位进程只有 4GB 的 RAM,否则它们仍然有 2GB 的 RAM 限制,就像在 32 位 Windows 中一样。我还听说 Solaris“将用户空间和内核空间映射到不同的 4GB 地址空间”quora.com/Why-do-32-bit-Linux-kernels-only-recognize-3GB-of-RAM
  • Ultra Sparc CPU 上的 Solaris 为用户和内核使用单独的地址空间,但 Sparc CPU 对此有特殊的硬件支持。 x86 CPU(和较旧的 Sparcs)上的 Solaris 使用分离的用户/内核地址空间。 docs.oracle.com/cd/E19620-01/805-3024/6j2sumi4b/index.html
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 2015-10-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多