线程栈分配

5
我们知道每个线程都有自己的堆栈。这些堆栈是从哪里分配的?我阅读了一些文档,似乎在创建线程时从堆中分配堆栈。这有意义吗?谢谢!

Linux线程堆栈分配的详细信息:其他线程的堆栈在进程虚拟地址空间中的位置在哪里?,以及动态增长它们是行不通的事实。 - Peter Cordes
2个回答

5
C语言没有规定内存来自哪里,这取决于操作系统和C运行时库。线程堆栈内存是由操作系统作为创建线程的系统调用的一部分分配的,或者创建线程的进程必须提供应用程序堆中的内存作为线程堆栈使用。查看Linux clone系统调用的文档,似乎Linux采用后者,即线程堆栈内存来自应用程序堆。您为什么要问?

1
我提出这个问题的原因是我对栈和堆有些困惑。通常人们说堆向上增长,栈向下增长,可能它们会相互重叠。但在多线程情况下,如果栈来自堆,那么栈或堆是否仍然可以增长到另一个中?谢谢。 - user3645364
这也取决于系统,但通常会设置某种“守卫页”,如果线程堆栈溢出,则会引发异常。在64位系统上,理论上当然可以为每个线程堆栈预先分配大量(连续的)虚拟地址空间,并根据需要支持物理内存,但我不知道这是否常见。 - Russell Borogove
谢谢你的回答。我需要进一步提问以便理解。对于一个多进程系统,系统有多少个堆?每个进程都有自己的堆还是所有进程共享一个全局堆?在多进程系统中,brk()或sbrk()如何工作?非常感谢您的帮助。 - user3645364
每个进程都有自己的堆。我对brk/sbrk的工作方式有点模糊,但我认为该进程开始时分配了大量虚拟地址空间和适量的物理内存,而brk/sbrk会将更多的物理内存用于支持虚拟内存。连续的虚拟空间可以由不连续的物理内存支持。 - Russell Borogove
1
非常感谢您的回答。我明白了。因此,即使所有进程都有不同的虚拟内存空间,但当调用内存分配例程(malloc()或new())时,最终内存来自公共物理内存空间(由brk/sbrk为进程保留)。这就是为什么我听说无论是new()还是malloc()成功都取决于整个系统内存的可用性。 - user3645364
1
是的,但虚拟机系统在已分配的虚拟内存空间超过可用物理内存时也可以交换到磁盘。 - Russell Borogove

2

有些系统内置线程支持,而其他系统则没有。对于不支持线程的系统,线程库将从堆中分配堆栈空间,并使用计时器实现线程切换。

拥有内置线程支持的系统通常会通过在地址空间中创建新页面来创建堆栈。理想情况下,它会在堆栈的每一端放置守卫页以检测溢出或欠流。


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