程序堆栈和堆是如何工作的?

30
我知道每个正在运行的进程都有与之关联的虚拟内存页面,其中一些页面将根据需要加载到主内存中。我也知道程序将具有堆栈和堆来分配动态内存。以下是我的问题。
  1. 堆栈是否也是主内存中某个页面的一部分?
  2. 当程序移动到等待状态时会发生什么?堆栈指针、程序计数器和其他信息存储在哪里?
  3. 为什么堆栈向下增长而堆向上增长?
  4. L1、L2缓存可以只包含一个连续内存块,还可以包含堆栈和堆的某些部分吗?
你能推荐一本涵盖这些内容的好书吗?
5个回答

17

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

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

当程序进入等待状态时会发生什么?栈指针、程序计数器和其他信息存储在哪里?

操作系统为每个正在运行的进程存储一个“上下文”。保存和恢复进程状态的操作称为“上下文切换”。

为什么栈向下增长而堆向上增长?

据我所知,这只是一种约定。栈实际上没有“增长”,它有固定的分配。

L1、L2缓存是否可以只包含一个连续的内存块,还是可以包含一部分栈和堆?

缓存只包含已使用的 RAM 部分的快照(最近使用或附近)。在任何时刻,它们都可以在其中具有地址空间的任何部分的内存。显示在哪里取决于缓存的结构参数(块长度、关联性、总大小等)。

我建议参考计算机体系结构:量化研究方法以了解底层硬件,以及任何操作系统书籍以了解硬件的“管理”。


Pep/8!! 这是一本很好的教学书,但我认为它对于一般学习来说相当糟糕。 - San Jacinto

8
这是我对这些问题的理解:
  1. 栈是否也是存储在主内存中某个页面中的一部分?

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

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

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

  3. 为什么栈向下增长而堆向上增长?

    因为它们通常必须共享同一地址空间,并且作为一种方便,它们各自从地址空间的一端开始。然后它们朝着彼此增长,形成了向下增长和向上增长的行为。

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

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


1
这是我在这组答案中第二次看到你的#3。你能告诉我你是从哪里得出这个推理的吗?我从来没有见过他们使用相同地址空间的保证,甚至没有任何暗示它非常普遍的东西。 - San Jacinto
1
它曾经是真实的,在早已过时和被丢弃的系统上。如今,在每个堆栈的末尾都有一个未映射的页面,因此堆栈溢出通常会导致段错误(这比践踏其他内存并继续执行更不可能成为可利用的安全漏洞)。在一个进程中可能有多个堆栈;例如,每个线程都有一个。也可能有多个堆。 - Jason Orendorff

3

3. 为什么栈向下增长而堆向上增长?

请注意,在某些系统(例如一些惠普系统)中,栈是向增长而不是向下增长。在其他系统(例如IBM/390)中,实际上根本没有硬件栈,而是从用户空间内动态分配的页面池。

堆可以在任何方向上增长,因为它可能包含许多分配和释放的空洞,所以最好将其视为松散的页面集合,而不是LIFO堆栈类型结构。尽管如此,大多数堆实现都会在预定的地址范围内扩展其空间使用,并根据需要进行增长和缩小。


2
当使用受保护模式操作系统(如Windows或Linux)时,每个进程都有一整堆内存页可供使用。如果需要更多内存,则可以分页加载更多内存。 通常,进程将其获得的内存分为两部分。一个是堆,另一个是栈。在arm上,栈底由栈指针r13指定,在x86上则由esp指定。当在堆栈上创建变量时,栈指针会移动以允许额外所需的空间。这是通过汇编器指令PUSH完成的。类似地,当变量超出其范围时,它就会从堆栈上POP下来。 通常,PUSH导致栈指针递减,使其值“在堆栈上”留下了上面的值。 内存的另一部分可以用于堆。然后可以使用malloc或new进行分配。每个线程必须有自己的堆栈,但可以与进程中的其他线程共享堆。 当内核重新安排线程时,它存储堆栈寄存器并更改堆栈寄存器以使用新堆栈。取决于它进行调度的方式,它可能需要存储程序计数器。 缓存与堆栈或堆没有任何关系。它由处理器管理,并提供一种方法以确保CPU所需的数据就在手边,以便它不必等待总线来获取数据。完全由CPU来确保主内存中的内容与缓存中存储的内容相同。唯一需要担心缓存的时间是使用DMA时。一个人将不得不手动刷新或同步缓存,以确保CPU不信任缓存并实际从主内存中提取数据。

2

你应该查看我架构课程中教授的幻灯片,链接为https://www.cis.upenn.edu/~cis501/。第六单元真的帮助我理解了你和其他人所问和回答的所有内容以及更多内容,如果你想要更深入的知识。


1
如果您能从那里引用一些有用的信息,或者至少将链接提交到archive.org,那么如果该网页被关闭(或更改),这仍将是一个有用的答案,那就太好了。事实上,我刚刚检查了一下,现在甚至没有发布幻灯片。 - RastaJedi

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