operating-system - 栈可以长成堆吗?
问题描述
我目前正在学习操作系统,我了解到堆栈位于内核和堆之间。令我困惑的是,在大多数实现中,由于堆栈倾向于向下增长而堆增长到更高的内存地址,是什么阻止了堆栈增长到堆中?如果有可能,如果它确实增长到堆中会发生什么?
解决方案
传统上,非常简化的内存视图看起来像这样:
===================
| Operating System | High memory
===================
| Your program |
| --------------- |
| | Process stack | |
| --------------- | Transient program area
| | Process heap | |
| --------------- |
| | Program code | |
| --------------- |
===================
| Operating system | Low memory
===================
正如您所指出的,进程堆栈在操作系统代码下方开始,并向下增长。另一方面,进程堆从固定程序代码的上方开始,然后向上增长。
在早期的 PC 操作系统中,这实际上是内存中程序的物理布局。例如,CP/M 操作系统为某些操作系统引导代码保留了前 256 个字节的内存,其余必要的操作系统服务占用了高内存区域。程序从地址 0x0100 开始,并且可以使用从那里到顶部操作系统代码开始之间的所有内存。MS-DOS 非常相似。
没有防护栏可以防止您提到的事情发生:程序会在堆栈上分配太多空间,以至于它会覆盖在堆上分配的内存。或者,程序将分配覆盖处理器堆栈的堆内存。当这些事情发生时,程序就会崩溃。在某些情况下,操作系统也会崩溃。当然,因为一次只能运行一个程序,这没什么大不了的:只需重新启动机器,然后再试一次。
现代计算机具有更先进的内存布局,而这种概念图不再适用。今天的操作系统可以更好地执行内存访问限制。例如,一个进程为其堆栈分配了一个固定段(通常大约为 1 兆字节)。如果程序试图使用比分配更多的堆栈空间,内存管理器将不允许它。该程序将因访问冲突而崩溃。出于同样的原因,程序的堆不能增长到分配给堆栈的内存中。
推荐阅读
- c# - 加入错误 | 无法创建仅原始类型的常量值
- javascript - 如何防止 find :submit 启用表单中的其余按钮?
- java - 通过Java执行curl
- python - 在数据框中替换“%”,然后将所有字符串转换为浮点数
- html - 我的 HTML 文件如何通过 gh-pages 访问我的 Javascript 文件?
- mysql - 将一行转换为多行的数据转换
- c# - 通过 UI 的 Unity 光线投射
- android - 与 AndroidManifest.xml 中的 Unresolved 类作斗争
- docker - 来自 Google Cloud Build Dockerfile 的 Google AppEngine ENV 变量
- c# - 将 SemaphoreSlim 用于具有返回类型的任务