我了解到,通过运行时地址绑定,程序可以在物理内存中非连续地分配帧。此外,如here和here所述,逻辑地址空间中程序的每个段都是连续的,但并非所有段都并排放置在一起。文本,数据,BSS和堆段放在一起,但堆栈段不是。换句话说,逻辑地址空间中堆和堆栈段之间(程序中断和堆栈顶部)之间存在未映射到物理地址空间中的任何帧的页面,因此暗示逻辑地址空间不是在运行时地址绑定的情况下是连续的。
但是在编译时或加载时绑定的情况下内存布局怎么样?既然逻辑地址空间不是抽象的地址空间而是实际的物理地址空间,那么程序如何在物理内存中布局?更具体地说,堆栈段如何放置在程序的物理地址空间中?它是与其他段放在一起还是单独放置,就像运行时绑定一样?
答案 0 :(得分:2)
要回答您的问题,我首先要解释一下现代操作系统中的stack
和heap
分配。
堆栈顾名思义就是继续内存分配,其中cpu使用push
和pop
命令从堆栈顶部添加/删除数据。我假设您已经知道堆栈是如何工作的。进程存储 - 堆栈上的返回地址,函数参数和局部变量。每次调用一个函数时,都会推送更多数据(最终可能会导致堆栈溢出,无法弹出任何数据 - 无限递归?)。当程序加载到内存中时,堆栈大小是固定的。大多数编程语言都允许您在编译期间决定堆栈大小。如果没有,他们将决定默认。在Linux上,最大堆栈大小(硬限制)受ulimit
限制。您可以按ulimit -s
检查并设置尺寸。
堆空间在* nix系统中没有上限(取决于,使用ulimit -v
确认),每个程序都以默认/设置的堆量开始,并且可以增加所需的数量。进程中的堆空间实际上是两个链接列表free
和used
块。每当从堆中需要内存分配时,将组合一个或多个空闲块以形成更大的块并将其作为单个块分配给使用的列表。释放意味着从使用列表中删除块到空闲列表。释放块后,堆可能有外部碎片。现在,如果空闲块的数量不能包含整个数据,则进程将从OS请求更多内存。通常,较新的块从较高地址分配。因此,我们显示了堆增长的向上方向图。我改写 - 堆不会在更高的方向上连续分配内存。
现在回答你的问题。
使用编译时或加载时地址绑定,堆栈和堆栈是怎样的 堆段放在程序的物理地址空间?
固定堆栈在编译时分配,带有一些堆内存。上面已经解释了如何放置。
堆和堆栈之间的空间是否为程序保留 或者OS可用于其他程序吗?
是的,它是为该计划保留的。但是,进程可以请求更多内存来在其堆中添加空闲块。它与共享它自己的堆不同。
注意:由于问题很广泛,因此可以在此处讨论很多主题。其中一些是 - 垃圾收集,块选择,共享内存等。我将很快在这里添加引用。
参考文献: -