内存空间中的映射区域和非映射区域有什么区别?

10
我在一篇关于malloc的文章中看到了以下段落。

堆是一个连续(在虚拟地址方面)的内存空间,具有三个边界:起点、最大限制(通过sys/resource.h中的函数getrlimit(2)和setrlimit(2)进行管理),以及称为“断点”的终点。断点标记映射内存空间的结尾,即虚拟地址空间的部分与实际内存相对应。

enter image description here

我想更好地理解映射区域和非映射区域的概念。


你能附上这篇文章的链接吗? - Aviv
http://www.learnme.in/malloc-c/ - Tordek
仔细阅读linux的手册后,当使用setrlimit来改变数据段大小(即堆、BSS和初始化数据部分)时,似乎只有软限制 - 即问题中提到的断点 - 有任何明确的影响,例如返回ENOMEM。然而,我无法确定硬限制 - 可能是问题中提到的rlimit - 所扮演的角色。 - Aviv
2个回答

16
如果内存地址是64位长的,就像在许多现代计算机中一样,你有18446744073709551616个可能的内存地址。(它取决于处理器架构实际可以使用多少位,但地址是使用64位存储的。)那比17亿GB更多,这可能比你的计算机实际拥有的内存还要多。因此,只有其中一部分17亿GB对应实际的内存。对于其余的地址,内存不存在。内存地址和内存位置之间没有对应关系。这些地址因此是未映射的。
这是一个简单的解释。实际上,情况要复杂一些。你的程序的内存地址不是你计算机中物理内存芯片,即实际内存地址。而是虚拟内存。每个进程都有自己的内存空间,即自己的18446744073709551616个地址,进程使用的内存地址由计算机硬件转换为物理内存地址。因此,一个进程可能在内存地址4711处存储了一些数据,而实际上是存储在这里的真实物理内存芯片上,另一个进程可能也在内存地址4711处存储了一些数据,但那是完全不同的地方,在那边存储在真正的物理内存芯片上。进程内部的虚拟内存地址被翻译或映射到实际的物理内存,但并不是全部,其余部分仍然未映射。
当然,这也是一个简化的解释。你可以使用比计算机中物理内存更多的虚拟内存。这是通过分页完成的,即将一些当前未使用的内存块(称为页面)存储在磁盘上,直到它们再次需要为止。(即使这个术语最初意味着将一个进程的所有内存写入磁盘,而不仅仅是其中的一部分,但仍然被称为“交换”)。

更麻烦的是,一些现代操作系统(如Linux和MacOS X,但据说不包括Windows)在分配内存时会出现过度承诺的情况。这意味着它们分配的内存地址比计算机上可以存储的地址更多,即使使用硬盘也无法存储。例如,我的电脑只有32GB的物理内存,并且只有4GB可用于将数据分页到磁盘上,因此实际可用的虚拟内存不能超过36GB。但是malloc(一种内存分配函数)却可以愉快地分配超过100,000GB的内存。只有当我实际尝试在所有该内存中存储东西时,它才与物理内存或磁盘连接。但它是我的虚拟内存空间的一部分,所以我认为这也是映射内存,即使它没有被映射任何东西。


1
除了Windows不会过度承诺内存。我听说它可能会为线程堆栈执行这个操作,以允许堆栈溢出异常处理,但这与Linux和其他操作系统完全不同:malloc不会分配超过RAM大小+页面文件的内存。 - user1143634

1
在堆中映射的区域指的是可以与物理内存一起映射的虚拟内存区域。而未映射的区域则表示未使用的虚拟内存空间,它不指向任何物理内存。
堆的映射区域和未映射区域之间的边界是系统断点。当使用malloc()请求一些内存时,系统断点会移动以扩大映射区域。Linux系统提供了brk()sbrk()方法来增加和减少系统断点的虚拟内存地址。

1
澄清一下,以防被误解,brk() 函数会减小堆的大小,而不是 sbrk() - KeyC0de
@RestlessC0bra,谢谢你。 - CWLiu
...而sbrk()增加它。 - KeyC0de

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接