windows的記憶體訪問是採用虛擬記憶體形式,即對於任何乙個adr,首先根據cr3暫存器的值來得到頁目錄表的位址,此時頁目錄表是乙個剛好大小為4k的頁。頁目錄表中,每一項大小為4b,內容包括對應頁表的實體地址和一些標誌位。由於頁表也是乙個大小為4k的頁,所以位址是按4k對齊的,因此這裡的位址只需要20位就可以了,剩下的12位作為標誌位。adr所在頁表的位址由頁目錄表的第adr>>22項給出。得到頁表的位址之後,同樣重複前面所做的工作,利用(adr<<10)>>22來得到所在頁在頁表中的索引,從而得到虛擬位址指向頁的實體地址,然後再根據頁內位址來定位讀取記憶體。至此,虛擬位址到實體地址的轉化過程結束。
但是在windows初始化的時候,前期是直接操縱實體地址的,通過分配乙個頁目錄表所在頁的位址和頁表所在大頁的位址,來直接操縱pte和pde。因為根據系統的記憶體布局,pde的位址是0xc0030000,pte的位址是0xc0000000,除此之外還有一些其他的系統預設虛擬位址空間,都是直接操縱pde和pte來進行初始化,同時更新相應的pfn資料庫。
在剛初始化完之後,windows的虛擬記憶體系統正式開始執行,一切對記憶體的訪問都需要虛擬位址。而之前我們所有做的操作都是在pde和pte上進行的,因此當前我們所有的位址都是pte和pde的虛擬位址,而我們真正需要的是pte和pde所指向的頁的虛擬位址。這是需要將我們前面所述的虛擬頁到頁表和頁目錄表的過程進行逆推。由於頁表的後22位是虛擬頁的位址,因此直接將頁表的虛擬位址左移10位即可得到虛擬頁的位址,剛好是以4k為單位對齊的。對於頁目錄表,也可以同樣的理解,因為頁目錄表的長度為4k,所以頁目錄表的表項的虛擬位址都是0xc0300開頭的,而且最後的兩位都是0,因為頁目錄表項的大小是4b對齊。左移10位之後,前10位變為1100000000,最後的十二位全部為0,剛好是以頁為單位對齊的,中間的10位剛好指向對應的頁表的虛擬位址索引。因此根據pte和pde可以直接得到它所指向物理頁面的虛擬位址,而且都是以頁為單位對齊的。
這裡需要注意的是,pte的大小為4mb,由於其虛擬空間是連續的,所以這個連續的空間在頁目錄表中佔據乙個表項,根據之前說過的方法和pte的虛擬位址空間,pte所在的頁目錄項為第0x300項,又因為每個項為4b,所以頁內位址為0xc00,所以最後的虛擬位址為0xc0300c00,其中的實體地址應該指向頁表的開始實體地址。而頁目錄表的大小為4k,剛好為一頁 ,他在pte中也佔據一項,由於頁目錄虛擬位址為0xc0300000,所以是頁表中的第0xc0300項,又因為頁表項也是4b對齊的,所以他距頁表開始位址的偏移為0x300c00因此頁目錄表的pte的虛擬位址為0xc0300c00。此外可以看出,頁表包括220頁,又因為頁表項的大小為4b,所以整個頁表所佔的虛擬空間的大小為222位,為0x400000。又因為頁表的虛擬位址開始為0xc0000000,所以結束位址為0xc0400000。所以頁目錄表的位址空間屬於頁表位址空間,即可以當pde使用又可以當作pte使用。兩個位址是相同的,因此為了使得在訪問pde和pte時得到正確的結果,必須設計使得pte和pde的資料格式一模一樣。因為pde和pte中的實體地址指向的都是乙個大小為4k的頁,所以一般情況下不會出問題。但是對於0xc0300c00這個位址,當作頁目錄項來使用時其中應該指向的是頁表0xc0000000的實體地址;而當作也表項來使用時,指向的應該是虛擬頁0xc0300000的位址,即頁目錄的實體地址。我們知道這兩個實體地址是不相同的,所以我們必須決定採用哪乙個實體地址。windows中採用的是使用cr3暫存器中的位址,即頁目錄表自己的實體地址。這個時候,如果程式需要訪問頁表內的某個位址,直接查pde的話,得到的位址還是cr3;再經過第二次查表來查詢pte,不過這個表仍然是當前的pde,只不過把他當作pte來使用,我們確保經過兩次查表之後所得的結果是正確的。
現在舉例子來說明。假設要訪問的位址(虛擬位址)為0xc0390c84。按照一般情況下,對於這個虛擬位址,我們首先得到頁目錄表的索引,為0x300項。這個項指向頁表的開始頁。然後再在頁表的開始頁中尋找頁表的索引,為0x390,得到乙個物理頁的位址,最後再根據頁內偏移0xc84得到所需位元組的內容。看上去我們根據流程得到了正確的結果 ,但是這個時候頁表的0x390項指的是虛擬位址為0x390000的頁面,再根據頁內偏移,我們最終得到的是虛擬位址為0x390c84所指向的內容,並不是我們希望得到的0xc0390c84所指向的內容。因此,把頁目錄表中的第0x300項按照常規設定為頁表0xc0000000的位址是不正確的。
而在頁目錄表中的第0x300項設定為cr3的位址,亦即頁目錄表自己的位址時,定址過程如下所示。首先根據頁目錄號0x300所指向的位址得到乙個頁表,其實也還是當前頁目錄。這時再根據頁表中的索引0x390,得到乙個頁的實體地址。然後再根據頁內偏移0xc84來得到最後所需的內容。注意,當前頁目錄表當作頁表使用時,裡面的項的相對偏移都是相對0xc0000000。這時頁表中0x390所指向的頁的虛擬位址為0xc0000000+(0x390<<12)==0xc0390000,的確是我們所希望訪問的虛擬頁。因此最後所得到的訪問內容是正確的。
windows 虛擬記憶體
虛擬記憶體的實現方法和過程 1 當乙個應用程式被啟動時,作業系統就建立乙個新的程序,被給每個程序分配2gb的虛擬位址 不是記憶體,只是位址 2 虛擬記憶體管理器將應用程式的 對映到那個那個應用程式的虛擬位址中的某個位置,並把當前所需要的 讀取到實體地址中 注意 虛擬位址和應用程式 的實體地址記憶體中...
虛擬記憶體管理
定義 虛擬記憶體是計算機系統記憶體管理的一種技術。它使得應用程式認為它擁有連續的可用的記憶體 乙個連續完整的位址空間 而實際上,它通常是被分隔成多個物理記憶體碎片,還有部分暫時儲存在外部磁碟儲存器上,在需要時進行資料交換。我的理解 程序例項在使用者態並不直接操作物理記憶體位址,實際物理記憶體是可能是...
windows筆記 虛擬記憶體
windows提供了3種進行記憶體管理的方法 虛擬記憶體,最適合用來管理大型物件或結構陣列。記憶體對映檔案,最適合用來管理大型資料流 通常來自檔案 以及在單個計算機上執行的多個程序之間共享資料。記憶體堆疊,最適合用來管理大量的小物件。pvoid virtualalloc pvoid pvaddres...