虚拟内存组织

虚拟内存组织

我有一个关于虚拟内存的问题。在描述中,我们总是倾向于显示堆从低地址向高地址增长,而堆栈则朝相反方向增长,例如

在此处输入图片描述


问题:这只是一种惯例,还是背后有某种逻辑?

答案1

这是一个现实中并不存在的老图表;自从引入分段和分页内存以来,它就不再存在了。

堆栈、堆和代码被分配为单独的内存段,因此它们永远不会相遇,也永远不会有重叠区域。每个段的大小都可以增加或减少到一个段大小的极限(这在 64 位中非常可观),甚至可以使用多个段(尤其是对于甚至不需要按顺序分配的堆)。段没有有意义的顺序,每个段都可以位于物理内存中的任何位置;逻辑地址连续的页面在物理内存中不需要连续(请参阅分页表)。

也许最好的例子是这张图片 维基百科 虚拟内存

在此处输入图片描述

答案2

这就是一些操作系统安排进程虚拟内存的方式。

在 Unix 上,更新已用内存量的一种方法是sbrk系统调用,它会告知它使用了多少内存。这意味着除堆栈之外的所有内存都以这种方式分配。堆栈通常以另一种方式增长,但这种方式是由 CPU(及其推送/弹出/调用/返回操作)暗示的。

但是使用动态库,代码和数据可以交错。一些系统还会将库随机放入内存中以防止某些攻击。(如果要修补/跳转的相关地址是随机设置的,则利用缓冲区溢出漏洞会更加困难)。

请注意,Unix 系统有sbrksyscall,但也可以分配内存,mmap可以在中间的任何位置分配内存。请参阅https://github.com/lattera/glibc/blob/master/malloc/malloc.c(Gnu/Linux malloc 的调用mmap位于第 2313 行)

答案3

逻辑是,除非你的程序很简单,否则编译器实际上并不知道堆需要多少内存以及堆栈需要多少内存,因此它会在内存的一端启动其中一个,在另一端启动另一个,并且由程序员确保它们不会相互冲突。

这是多任务和虚拟内存出现之前的工作方式。正如其他答案所指出的,支持这些功能的操作系统(包括几乎所有现代台式电脑、服务器和移动设备)将堆和堆栈映射到由操作系统管理且不重叠的虚拟内存段中。

然而,存在于同一物理内存中的堆和栈模型仍然与许多嵌入式系统(如物联网设备)相关。

相关内容