提问人:Olle Härstedt 提问时间:1/9/2021 最后编辑:Priyanshul GovilOlle Härstedt 更新时间:1/11/2021 访问量:222
为什么在大多数操作系统的运行时不能增加堆栈?
How come the stack cannot be increased during runtime in most operating system?
答:
在程序执行期间,用于堆栈的空间会频繁增加和减少,因为函数被调用和返回。堆栈允许的最大空间通常是一个固定限制。
在较旧的计算机中,内存是一种非常有限的资源,它可能仍然存在于小型设备中。在这些情况下,硬件功能可能会对最大堆栈大小施加必要的限制。
在具有大量内存的现代系统中,可能有大量内存可用于堆栈,但允许的最大值通常设置为某个较低的值。这提供了一种捕捉“失控”程序的方法。通常,控制程序使用的堆栈空间量是软件工程中被忽视的部分。根据实践经验设定了限制,但我们可以做得更好。1
从理论上讲,一个程序可以被赋予一个很小的初始限制,如果它发现自己正在处理一个“大”问题,它可以告诉操作系统它打算使用更多。这仍然可以捕获大多数“失控”的程序,同时允许精心设计的程序使用更多空间。但是,总的来说,我们设计的程序使用堆栈进行程序控制(管理函数调用和返回,以及为本地数据提供适度的空间)和其他用于操作数据的内存。因此,堆栈空间很大程度上是程序设计(固定的)的函数,而不是问题的大小。该模型运行良好,因此我们继续使用它。
脚注
1 例如,对于每个不使用具有运行时变量大小的对象的例程,编译器可以报告该例程在通过它的任何路径中使用的最大空间。对于任何调用树 [因此没有循环] 链接器或其他工具可以报告使用的最大堆栈空间。其他工具可以帮助分析具有潜在递归的调用图中的堆栈使用情况。
为什么在大多数操作系统的运行时不能增加堆栈?
这对 Linux 来说是错误的。在最近的 Linux 系统上, 每个线程都有自己的调用堆栈 (参见 pthreads(7)), 并且应用程序可以(通过巧妙的技巧)在查询调用堆栈后使用 mmap(2) 和 mremap(2) 增加一些调用堆栈(参见 proc(5) 和 use ),就像 pmap(1) 一样。/proc/
/proc/self/maps
当然,此类代码是特定于体系结构的,因为在某些情况下,调用堆栈会朝着增加地址的方向增长,而在其他情况下,调用堆栈会朝着减少地址的方向增长。
另请阅读操作系统:Three Easy Pieces 和 OSDEV wiki,并研究 GNU libc 的源代码。
顺便说一句,Appel 的书 Compiling with Continuations,他的旧论文 Garbage Collection 可能比 Stack Allocation 更快,这篇关于使用 Continuations 和 LLVM 编译的论文可能会让您感兴趣,两者都与您的问题非常相关:有时,几乎没有“没有调用堆栈”,并且“增加它”是没有意义的。
评论
malloc