即使内存可用,小堆栈的基本原理是什么?

时间:2011-09-23 05:01:58

标签: operating-system

最近,我在接受采访时被问到,为什么当可用内存没有限制时你会有一个较小的堆栈?即使你有4GB的物理内存,为什么你会在1KB范围内拥有它?这是标准的设计实践吗?

7 个答案:

答案 0 :(得分:7)

其他答案都很好;我只是想我会指出问题中固有的一个重要误解。 您拥有多少物理内存完全不相关。拥有更多物理内存只是一种优化;它可以防止必须使用磁盘作为存储。堆栈消耗的宝贵资源是地址空间,而不是物理内存。现在没有使用的堆栈位甚至不会驻留在物理内存中;他们将被分页到磁盘。但是一旦提交,他们就会占用虚拟地址空间。

答案 1 :(得分:5)

你的筹码越少,你就越多。 1kB堆栈是没用的,因为我无法想象一个页面很小的架构。更典型的尺寸是128kB-1MB。

由于每个线程都有自己的堆栈,因此您可以拥有的堆栈数量是您可以拥有的线程数量的上限。有些人抱怨他们无法在32位Windows进程的标准2GB地址空间中创建超过2000个线程,因此有些人希望更小的堆栈允许更多线程,这并不奇怪。

另外,考虑到如果必须提前完全保留堆栈,它会在地址空间中划出一个块,直到堆栈不再使用(即线程退出)才能返回。那段保留的地址空间然后限制了你可以进行的连续分配的大小。

答案 2 :(得分:1)

我不知道“真实”的答案,但我的猜测是:

  • 它是按需提交的。

  • 你真的需要吗?

如果系统使用1 MiB作为堆栈,那么一个拥有1024个线程的典型系统将使用1 GiB内存(大部分)没有...这可能不是你想要的,特别是因为你没有需要它。

答案 3 :(得分:1)

一个原因是,即使现在内存很大,它仍然无限制。 32位进程通常限制为4GB的地址空间(是的,您可以使用PAE来增加它,但这需要来自操作系统的支持并返回到分段内存模型。)每个线程都会占用一些内存用于它的堆栈,如果一个堆栈的大小是兆字节 - 无论它是否被分页 - 它占据了应用程序地址空间的重要部分。

堆栈越小,您可以挤入应用程序的线程越多,并且您可以为其他所有内容提供的内存越多。理想情况下,您希望堆栈的大小足以处理通过线程的所有可能的控制流,但要小到足以使您没有浪费的地址空间。

答案 4 :(得分:1)

这里有两件事。首先,堆栈大小的限制将限制系统中的进程/线程数。然后,限制不是因为物理内存的大小,而是因为可寻址虚拟内存的限制。其次,很少进程/线程需要更多的堆栈大小,如果他们这样做,他们可以要求它(库无缝地处理它)。因此,在启动新的进程/线程时,给它们一个小的堆栈空间是有意义的。

答案 5 :(得分:1)

其他答案在这里已经提到了核心概念,堆栈中最重要的消耗资源是地址空间(因为它的实现需要大量连续的地址空间),并且每个线程在Windows上消耗的默认空间并不是无关紧要的。

然而,完整的故事在很多层次和层次上都非常微妙(并且可以并且会随着时间的推移而变化)。

马克·鲁西诺维奇(Mark Russinovich)作为他的“推动Windows的极限”系列的一部分进入了extremely detailed levels of analysis。这项工作绝不是一篇介绍性的文章,大多数人都不会认为这是在求职面试中应该知道的那种事情,除非你在那个特定领域的工作面试。

答案 6 :(得分:0)

也许因为每次调用函数时,操作系统都必须将内存分配给该函数的堆栈。因为函数可以链接,所以几个函数调用将产生更多的堆栈分配。像4GiB这样的大型默认堆栈大小是不切实际的。但那只是我的猜测......