2010-11-23 93 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 ==具有相同保護/狀態的連續頁面組。

如果與區域相關聯 的保護屬性對 致力於存儲沒有任何影響,我們爲什麼需要它?

如上所述。