我的理解是Linux内核在每个进程启动之前都会给它分配一个栈,这个初始大小是可配置的。进程可以PUSH
通过CPU指令直接向堆栈传送数据,即在每个这样的步骤中不涉及操作系统。
然而,在某些时候,该PUSH
操作可能会超过分配的堆栈大小,并且根据内核是否可以分配更大的堆栈大小,可能会发生多种情况。
我的问题是:在初始之后会发生什么PUSH
?系统如何检测“堆栈溢出”,并且它需要生长堆栈直到最终简历流程的执行?
如果有帮助的话,我们可以关注 x86 架构。
我想我们有以下各方参与:
- 中央处理器
- 内存管理单元
- 核心
- 过程
例如,谁检测到“堆栈溢出,是CPU吗?MMU?这是否会导致发出硬件中断?还有别的事吗?如果是这样,谁处理这里的事情? (直到堆栈最终扩展,并且进程可以恢复其下一条CPU指令?)
答案1
MMU 将在堆栈的预期大小之后留下一些填充无效内存地址的填充,如果您尝试将堆栈增长得太多,您将最终取消引用和无效内存地址,并且 MMU 将抛出段错误。
您还可以使用金丝雀价值观在堆栈中,但我不会进入。
通常编译器会对代码进行静态分析,并尝试找到堆栈所需的大小,以防止堆栈大小调整。-fstack-usage 让您深入了解 gcc 的作用
C 标准定义,当 C 堆栈需要增长时,它将隐式调用 mremap,这意味着 Linux 内核会自行处理所有这些事情。
一个过于简化时间线看起来像这样:
推->MMU 段错误->Linux 检测到它->Linux 重新映射内存->值已插入->节目继续进行
我强烈建议您不要将此视为明确的答案,并阅读有关该主题的更多信息,因为我不是专家。