【问题标题】:How come the stack cannot be increased during runtime in most operating system?在大多数操作系统中,为什么堆栈不能在运行时增加?
【发布时间】:2021-04-14 22:44:25
【问题描述】:

是为了避免碎片化吗?还是其他什么原因?与具有手动生命周期的malloc() 相比,为内存分配设置生命周期是一个非常有用的结构。

【问题讨论】:

  • 为什么用 C 标记?我在这里看不到任何特定于 C 的内容 - 除了对 malloc 的引用。
  • @4386427 有什么更好的标签?
  • 也许操作系统会更合适。
  • @EricPostpischil 你能把它写成答案吗?

标签: c operating-system stack-allocation


【解决方案1】:

在程序执行过程中,用于堆栈的空间会随着函数的调用和返回而频繁增加和减少。堆栈允许的最大空间通常是一个固定限制。

在较旧的计算机中,内存是一种非常有限的资源,它可能仍然存在于小型设备中。在这些情况下,硬件能力可能会对最大堆栈大小施加必要的限制。

在具有大量内存的现代系统中,堆栈可能有很多可用空间,但允许的最大值通常设置为较低的值。这提供了一种捕获“失控”程序的方法。通常,控制程序使用多少堆栈空间是软件工程中被忽视的部分。限制是根据实际经验设置的,但我们可以做得更好。1

理论上,可以给一个程序一个小的初始限制,如果它发现自己正在处理一个“大”问题,它可以告诉操作系统它打算使用更多。这仍然可以捕获大多数“失控”程序,同时允许精心设计的程序使用更多空间。然而,总的来说,我们设计的程序使用堆栈进行程序控制(管理函数调用和返回,以及用于本地数据的适度空间)和其他内存用于正在操作的数据。所以堆栈空间在很大程度上是程序设计(固定)而不是问题大小的函数。该模型运行良好,因此我们继续使用它。

脚注

1 例如,对于每个不使用具有运行时可变大小的对象的例程,编译器可以报告该例程在通过它的任何路径中使用的最大空间。链接器或其他工具可以报告任何调用树[因此没有循环]使用的最大堆栈空间。其他工具可以帮助分析调用图中具有潜在递归的堆栈使用情况。

【讨论】:

    【解决方案2】:

    为什么大多数操作系统在运行时堆栈不能增加?

    这对于 Linux 来说是错误的。在最近的 Linux 系统上,每个线程都有自己的call stack(参见pthreads(7)),并且应用程序可以(通过巧妙的技巧)在通过/proc/ 查询调用堆栈后使用mmap(2)mremap(2) 增加一些调用堆栈(参见proc(5) 并使用/proc/self/maps),例如pmap(1) 会。

    当然,这样的代码是特定于体系结构的,因为在某些情况下,调用堆栈会随着地址的增加而增长,而在其他情况下,地址会随着地址的减少而增长。

    另请阅读Operating Systems: Three Easy PiecesOSDEV wiki,并研究GNU libc 的源代码。

    顺便说一句,Appel 的书Compiling with Continuations、他的旧论文Garbage Collection can be faster than Stack AllocationCompiling with Continuations and LLVM 上的这篇论文可能会让您感兴趣,并且两者都与您的问题非常相关:有时,几乎“没有调用堆栈”并且它使没有意义“增加它”。

    【讨论】:

    • 这是一个受支持的事情,比如“让我的堆栈更大”的调用,还是一个自己动手做的事情,比如“找到我的堆栈映射的末尾在哪里,然后映射更多的内存” ?如果是后者,如何找到堆栈映射的结束位置?明确给出的东西告诉你结束在哪里(或者,等效地,堆栈有多大)或其他什么?
    猜你喜欢
    • 2020-06-15
    • 2014-05-27
    • 2012-05-04
    • 2010-10-14
    • 2017-04-16
    • 2021-04-02
    • 2017-06-29
    • 2020-09-26
    相关资源
    最近更新 更多