为什么我们不把整个堆栈都做成保护页?Why don’t we just make the entire stack out of guard pages?
文章探讨了为什么在系统设计中不将整个堆栈都设置为保护页。通过分析保护页的作用和限制,解释了全面使用保护页可能带来的性能问题和系统开销,从而说明了在堆栈管理中需要平衡安全与效率。
Raymond Chen
在我之前关于不同架构的编译器如何执行栈探测的概述中,Cole Tobin 问道:“为什么不设置一个页面错误处理程序,检测发生错误的地址是否在栈上,并调入其他页面呢?”
Csaba Varga 回复道:“我猜:你不会希望一个无效的指针解引用仅仅因为碰巧指向了栈最终可能增长到的位置,就分配一大块栈空间。大多数情况下,你希望无效的指针解引用会引发段错误。”
在这一点上我同意 Csaba 的看法。
如果整个栈都由保护页组成,那就意味着在栈边界下方很远的地方发生的一个页面错误,可能会耗费任意长的时间并分配任意大的内存。程序可能设定了默认 1GB 的栈空间,而现在栈上的一个页面错误就可能导致系统在分配 1GB 内存时出现长时间的暂停。如果你在调试器中研究这个问题,你会看到一次内存读取竟然需要好几分钟。
更糟糕的是,由于这发生在内核模式下,你根本无法阻止它。你看到某个程序开始膨胀并消耗系统的所有内存,于是你打开任务管理器去终止它,但这个进程却死不掉。它只会继续膨胀!
即使保护页不止一页,它也仍然是一个较小的固定页数,系统可以在短时间内处理完保护页错误。更重要的是,其工作量是有界的。
作者
Raymond 参与 Windows 的演进已有 30 多年。2003 年,他创办了一个名为 The Old New Thing 的网站,其受欢迎程度远远超出了他最疯狂的想象,这一发展至今仍让他感到有些心惊肉跳。这个网站后来衍生出了一本书,巧合的是书名也叫《The Old New Thing》(Addison Wesley 2007 年出版)。他偶尔会出现在 Windows Dev Docs 的 Twitter 账号上讲些故事,不过这些故事并没有传达任何有用的信息。
需要完整排版与评论请前往来源站点阅读。