繁体   English   中英

有关内存页面保护的问题

[英]Question about memory page protection

这是我阅读《通过C / C ++ 5th Edition的Windows》时遇到的另一个问题。 首先,让我们看一下报价。

LPVOID WINAPI VirtualAlloc(
  __in_opt  LPVOID lpAddress,
  __in      SIZE_T dwSize,
  __in      DWORD fdwAllocationType,
  __in      DWORD fdwProtect
);

最后一个参数fdwProtect指示应分配给该区域的保护属性。 与该区域关联的保护属性对映射到该区域的已提交存储没有影响。

保留区域时,分配最常与提交给该区域的存储一起使用的保护属性。 例如,如果您打算使用PAGE_READWRITE的保护属性来提交物理存储,则应使用PAGE_READWRITE保留该区域。 当区域的保护属性与提交的存储的保护属性匹配时,系统的内部记录保留行为将更加有效。

(提交存储时)... 尽管可以指定其他保护属性通常传递与调用VirtualAlloc保留区域时使用的页面保护属性相同的页面保护属性。

上面的话完全使我感到困惑。

  • 如果与该区域关联的保护属性对提交的存储没有影响,为什么我们需要它?

  • 由于建议对保留和提交使用相同的保护属性,因此Windows为什么仍向我们提供使用不同属性的选项? 这不是误导性的,而是一种悖论吗?

  • 分别为保留区域和已提交存储将保护属性存储在何处?

非常感谢您的见解。

在上下文中阅读它很重要。

与该区域关联的保护属性对映射到该区域的已提交存储没有影响。

是指保留而不是提交区域。

保留页没有后备存储,因此从概念上讲,它的保护始终是PAGE_NOACCESS, 无论您传递给VirtualAlloc什么 即,如果线程尝试读取/写入保留区域中的地址,则会引发访问冲突。

从链接的文章:

保留地址始终为PAGE_NOACCESS,这是系统强制执行的默认值,无论将什么值传递给函数。 提交的页面可以是只读,读写或无访问权限。

回覆:

  • 分别为保留区域和已提交存储将保护属性存储在何处?

每个过程中,虚拟地址区域的保护属性都存储在VAD树中。 (VAD ==虚拟地址描述符,请参阅Windows Internals或链接的文章)

由于建议对保留和提交使用相同的保护属性,因此Windows为什么仍向我们提供使用不同属性的选项? 这不是误导性的,而是一种悖论吗?

因为该函数始终接受保护参数,但是其行为取决于fdwAllocationType 保护仅对已落实的存储有意义。

Richter建议使用相同保护设置的原因大概是因为区域中保护标志的更改较少意味着“块”较少(请参阅您的书以获取定义),因此VAD的AVL树较小。 即,如果一个区域中的所有页面都提交有相同的标志,则只有1个块。 否则,该区域中的块数可能与页面数一样。 每个块(而非页面)都需要一个VAD。

块==具有相同保护/状态的连续页面集。

如果与该区域关联的保护属性对提交的存储没有影响,为什么我们需要它?

如上。

嗯...一个原因可能是您可以使用保护页,以便在使用内存时提交内存。

想想Windows中的线程堆栈; 堆栈正下方的页面被设置为保护页面,通常具有读写功能。 触摸防护页面后,异常处理程序将运行并提交防护页面,并使下一页成为防护。

请参阅此处以获得更好的描述。 此外,该链接是有关Windows如何处理低级资源的系列文章的一部分,非常好阅读。

允许您重新指定保护属性的另一个原因可能是写时复制技术。 页面设置为只读,直到它们被更改为止,这可能引发异常,您可以处理等,等等。

在386系列Intel芯片上,提交,读/写/保留标志存储在页表中。 请查看386芯片参考以获取更多详细信息。 编辑:我戳了一下,找不到MS存储PAGE_GUARD位的位置。 现在我很好奇我在哪里看到它。 :)太可惜了,去年春天我扔掉了约500磅的旧参考资料...

希望这可以帮助 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM