2010-11-23 95 views
1

下面是我在通过C/C++第5版阅读< Windows时遇到的另一个问题。首先,让我们看看一些报价。关于内存页面保护的问题

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

最后一个参数,fdwProtect, 表示保护属性 应分配给区域。 与区域关联的保护属性对映射到 区域的已提交存储无效。

当预留区域,指定将与存储使用 最常见的保护属性致力于 该地区。例如,如果您 打算提交 保护属性 PAGE_READWRITE,您应该保留带有PAGE_READWRITE的 区域。 当 区域的保护属性匹配 已提交存储的保护 属性时, 系统的内部记录保留 的行为更有效。

(当commiting存储)......你平时 传递相同的页面保护 时 的VirtualAlloc被称为预留 区域,虽然你可以指定一个 不同的保护属性是使用属性。

以上引用完全让我感到困惑。

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

  • 由于推荐为保留和提交使用相同的保护属性,为什么Windows仍为我们提供使用不同属性的选项?难道它不是领先的,而是一种悖论?

  • 究竟哪里是保护属性存储保留区域致力于存储,repectively?

非常感谢您的见解。

回答

2

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

想想Windows中的线程堆栈;紧挨在堆栈下面的页面被设置为防护页面,通常具有读写能力。一旦触发了防护页,异常处理程序就会运行并提交防护页,并使下一页成为警戒。

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

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

在386系列英特尔芯片上,提交,读/写/保留标志存储在页面中表。请查看386 chip reference了解更多详情。 编辑:我戳了一下,无法找到MS存储PAGE_GUARD位的位置。现在我很好奇我在哪里看到它。 :)太糟糕了,我抛出了大约500磅旧参考资料去年春天..​​.

希望这有助于:)

+0

感谢您的回复,我会看看链接。 – smwikipedia 2010-11-23 09:20:08

+0

由于守卫页面,堆栈似乎可以自动增长。如果没有CPU硬件的支持,我认为这是不可能实现的。 PAGE_GUARD属性存储在Page Table Entry(PTE)中,CPU可以检测对这样的页面的访问并触发异常。我对吗? – smwikipedia 2010-11-23 09:34:35

3

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

与所述区域相关联 保护属性对映射到 区域 致力于存储没有影响。

指的是保留,而不是承诺区域。

保留页面没有后备存储,所以它的保护总是在概念上PAGE_NOACCESS,regardless of what you pass to VirtualAlloc。即如果线程试图读取/写入保留区域中的地址,则会引发访问冲突。

从链接的文章:

保留的地址总是 PAGE_NOACCESS,由 系统强制不管是 传递给函数什么样的价值默认。承诺 页面可以是只读的, 可读写或无访问。

回复:

  • 究竟哪里是存储保留区域 并致力于存储保护 属性,repectively?

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

既然是建议使用这两种预约和犯同样的保护属性,为什么Windows仍然为我们提供了使用不同属性的选项?难道它不是领先的,而是一种悖论?

因为该函数总是接受保护参数,但其行为取决于fdwAllocationType。保护仅对承诺的存储有意义。

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

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

如果与区域相关联 的保护属性对 致力于存储没有任何影响,我们为什么需要它?

如上所述。