这是我在阅读时遇到的另一个问题< Windows通过C / C ++第5版>。首先,让我们看一些报价。
LPVOID WINAPI VirtualAlloc(
__in_opt LPVOID lpAddress,
__in SIZE_T dwSize,
__in DWORD fdwAllocationType,
__in DWORD fdwProtect
);
最后一个参数fdwProtect, 表示保护属性 应该分配给该地区。 与该区域关联的保护属性对该区域没有影响 提交的存储映射到 区域。
保留区域时,请指定将使用的保护属性 最经常的存储承诺 到该地区。例如,如果你 打算提交物理存储 保护属性 PAGE_READWRITE,你应该保留 PAGE_READWRITE的区域。的的 系统的内部记录保存 表现得更有效率 region的保护属性匹配 承诺存储的保护 属性。
(提交存储时)...通常 传递相同的页面保护 在何时使用的属性 调用VirtualAlloc来保留 region,虽然你可以指定一个 不同的保护属性。
上述引文让我感到困惑。
如果与该区域关联的保护属性对已提交的存储没有影响,我们为什么需要它?
由于建议对预留和提交使用相同的保护属性,为什么Windows仍然为我们提供使用不同属性的选项?这不是一个错误的领导和一种悖论吗?
保留区域和已提交存储空间的保护属性究竟在哪里?
非常感谢您的见解。
答案 0 :(得分:3)
在上下文中阅读它很重要。
相关的保护属性 与该地区没有任何影响 提交的存储映射到 区域。
指的是保留,而不是提交区域。
保留页面没有后备存储,因此它的保护始终是概念上的PAGE_NOACCESS,regardless of what you pass to VirtualAlloc。即如果线程尝试读/写保留区域中的地址,则会引发访问冲突。
来自链接文章:
始终是保留地址 PAGE_NOACCESS,由。强制执行的默认值 系统无论有什么价值 传递给函数。承诺 页面可以是只读的, 读写或无访问权。
回复:
- 确切地说是保护 为保留区域存储的属性 和承诺存储,分别?
虚拟地址区域的保护属性按进程存储在VAD树中。 (VAD ==虚拟地址描述符,请参阅Windows Internals或链接文章)
由于建议对预留和提交使用相同的保护属性,为什么Windows仍然为我们提供使用不同属性的选项?这不是错误的领导和一种悖论吗?
因为该函数始终接受保护参数,但其行为取决于fdwAllocationType
。保护仅对提交的存储有意义。
Richter建议使用相同的保护设置的原因可能是因为区域中保护标志的更改意味着更少的“块”(参见本书的定义),因此VAD的AVL树更小。即如果区域中的所有页面都使用相同的标志进行提交,则只有1个块。否则,该区域中的页面可能会有多个块。你需要为每个块(而不是页面)使用VAD。
阻止==具有相同保护/状态的连续页面集。
如果保护属性关联 与该地区没有任何影响 承诺存储,为什么我们需要它?
如上所述。
答案 1 :(得分:2)
嗯......有一个原因可能是你可以使用防护页面,这样你就可以在使用时提交内存。
想想Windows中的线程堆栈;堆栈正下方的页面被设置为保护页面,通常具有读写能力。触摸防护页面后,将运行异常处理程序并提交防护页面并使下一页成为防护页面。
有关更好的说明,请参阅here。此外,该链接是关于Windows如何处理低级资源的系列文章的一部分,并且阅读非常好。
允许您重新指定保护属性的另一个原因可能是写入技术上的复制。页面设置为只读,直到它们被更改,这可能会引发您可以处理的异常等等。
在386系列Intel芯片上,提交,读/写/保留标志存储在页表中。有关详细信息,请查看386 chip reference。 编辑:我戳了一下,找不到MS存储PAGE_GUARD位的位置。现在我很好奇我看到它的地方。 :)太糟糕了我去年春天丢掉了大约500磅的旧参考材料......
希望这会有所帮助:)