程序堆栈和堆,它们如何工作?

时间:2010-01-14 19:52:45

标签: stack kernel heap

我知道每个正在运行的进程都在虚拟内存中有与之关联的页面,其中很少会根据需要加载到主内存中。我也知道程序将有一个堆栈,也有一个堆来分配动态内存。这是我的问题。

  1. 堆栈也是主内存中某个页面的一部分吗?
  2. 当程序进入等待状态时会发生什么?堆栈指针,程序计数器和其他信息存储在哪里?
  3. 为什么堆栈会逐渐减少并且堆积增长?
  4. L1,L2缓存是否只包含一块连续内存,或者它可以包含堆栈和堆的某些部分?
  5. 你能推荐一本涵盖这些内容的好书吗?

5 个答案:

答案 0 :(得分:14)

  1. 是 - 堆栈通常存储在内存的“低”地址中,并向上填充其上限。堆通常存储在地址空间的“顶部”,并朝堆栈增长。

  2. O / S为每个正在运行的进程存储“上下文”。保存和恢复进程状态的操作称为“上下文切换”。

  3. 只是一个常规AFAIK。堆栈并没有真正“增长”它有固定的分配。

  4. 缓存只包含已使用的RAM部分(最近或附近)的快照。在任何时候,他们都可以从地址空间的任何部分获取内存。显示的内容在很大程度上取决于缓存的结构参数(块长度,关联性,总大小等)。

  5. 我建议Computer Architecture: A Quantitative Approach作为底层硬件的好参考,以及有关如何“管理”硬件的操作系统的任何书籍。

答案 1 :(得分:7)

这是我对这些问题的理解:

  1. 堆栈是否也是主内存中某个页面的一部分?

    是的,堆栈通常也存储在进程地址空间中。

  2. 程序移动到等待状态时会发生什么,堆栈指针,程序计数器和其他信息存储在哪里?

    当操作系统将进程从活动状态转换为等待状态时,它将所有寄存器(包括堆栈指针和程序计数器)存储在内核的进程表中。然后,当它再次变为活动状态时,操作系统会将所有信息复制回原位。

  3. 为什么堆栈会逐渐减少并且堆积增长?

    因为他们通常必须共享相同的地址空间,并且为方便起见,他们每个都从地址空间的一端开始。然后他们互相生长,让这种成长成长。

  4. L1,L2缓存是否只包含一个连续内存块,或者它可以包含堆栈和堆的某些部分?

    CPU缓存将存储最近使用的内存块。因为堆栈和堆都存储在主内存中,所以缓存可以包含两者的一部分。

答案 2 :(得分:3)

第3。为什么堆栈增长和堆增长?

请注意,在某些系统(例如某些HP系统)上,堆栈 up 而不是down。在其他系统(例如,IBM / 390)上,根本没有没有真实硬件堆栈,而是从用户空间内存动态分配的页面池。

通常,堆可以在任何方向上增长,因为它可能包含许多分配和释放漏洞,因此最好将其视为松散的页面集合而不是LIFO - 堆型结构。话虽这么说,大多数堆实现都会在预定的地址范围内扩展其空间使用量,并在必要时增加和缩小它。

答案 3 :(得分:1)

当使用受保护模式操作系统(如Windows或Linux)时,每个进程都有一大堆内存页面可供给定进程使用。如果需要更多内存,可以分页更多内容。

通常,该过程将给定的内存分为两部分。一个是堆,另一个是堆栈。堆栈的底部由arm上的堆栈指针r13和x86上的esp指定。当在堆栈上创建变量时,移动堆栈指针以允许所需的额外空间。这是由汇编指令PUSH完成的。类似地,当变量超出范围时,它会从堆栈中弹出。

通常,PUSH会导致堆栈指针递减,并使堆栈指针值高于堆栈指针值。

内存的另一部分可用于堆。然后可以使用malloc或new进行分配。每个线程必须有自己的堆栈,但可以与进程中的其他线程共享堆。

当内核重新安排一个线程时,它会存储堆栈寄存器并将堆栈寄存器更改为新堆栈。如果可能需要或可能不需要存储程序计数器,具体取决于调度方式。

缓存与堆栈或堆无关。它由处理器管理,并提供一种方法来确保CPU所需的数据即将到来,这样就不必等待总线获取它。完全由CPU来确保主存储器中的内容与存储在缓存中的内容相同。真正需要担心缓存的唯一时间是使用DMA。必须手动刷新或同步缓存,以确保CPU不信任缓存并实际从主内存中提取数据。

答案 4 :(得分:1)

你应该从我的建筑类中查看我教授的slides。第六部分。真的帮助我理解,你要求的所有人和其他人已经回答了,如果你想要更深入的知识,还有更多。