虛擬記憶體 分頁機制

2021-09-26 02:00:17 字數 4159 閱讀 8301

1.2 分頁

1.3 頁表

1.4 加速分頁過程

1.5 針對大記憶體的頁表

虛擬記憶體的基本思想:每個程式都有自己的位址空間,這個空間被分割成多個塊,每乙個塊被稱作一頁或頁面。每一頁有連續的位址範圍。這些頁被對映到物理記憶體,但並不是所有的頁都必須在記憶體中才能執行程式。當程式引用到一部分在物理記憶體中的位址空間時,由硬體立刻執行必要的對映。當程式引用到一部分不在物理記憶體中的位址空間時,由作業系統負責將缺失的部分裝入物理記憶體並重新執行失敗的指令。

程序記憶體空間通過分段儲存來管理

核心總是駐留在記憶體中,是作業系統的一部分。核心空間為核心保留,不允許應用程式讀寫該區域的內容或直接呼叫核心**定義的函式。

大部分虛擬記憶體系統中都使用一種稱為分頁的技術。

由程式產生的位址稱為虛擬位址,它們構成了乙個虛擬位址空間。在沒有虛擬記憶體的計算機上,系統直接把虛擬位址送到記憶體匯流排上,讀寫操作使用具有相同位址的物理記憶體字;而在使用虛擬記憶體的情況下,虛擬位址不是被直接送到記憶體匯流排上,而是被送到記憶體管理單元(memory management unit,mmu),mmu把虛擬位址對映為物理記憶體位址。

虛擬位址空間按照固定大小劃分成被稱為頁面(page)的若干單元。在物理記憶體中對應的單元稱為頁框。頁面和頁框的大小通常是一樣的。實際系統中的頁面大小從512位元組到1gb。

栗子:一頁4kb,64kb的虛擬位址空間和32kb的物理記憶體可得到16個虛擬頁面和8個頁框。從虛擬位址到實體地址的流程:

在上圖中,虛擬位址8196(二進位制是0010 0000 0000 0100),輸入的16位虛擬位址被分為4位的頁號和12位的偏移量。4位的頁號可以表示16個頁面,12位的偏移量可以為一頁內的全部4096個位元組編址。

可用頁號作為頁表的索引,以得出對應於該虛擬頁面的頁框號。如果「在/不在」位是0,則引起缺頁中斷。如果該位是1,則將在頁表中查到的頁框號複製到輸出暫存器的高3位中,再加上輸入虛擬位址的低12位偏移量。如此就構成了15位的實體地址。輸出暫存器的內容隨即被作為實體地址送到記憶體匯流排。

此處討論缺頁中斷(或稱為缺頁錯誤)發生的事:假如作業系統訪問虛擬頁面b產生缺頁中斷,決定放棄頁框1(對應虛擬頁面a),那麼它將把產生缺頁中斷所對應的虛擬頁面(頁面b)裝入頁框1的起始實體地址,並對mmu對映做兩處修改:首先,它要將原來頁框1所對應的虛擬頁面(頁面a)的表項設為未對映,使以後任何對原來虛擬頁面(頁面a)的訪問都導致陷阱。隨後,把引起缺頁中斷(頁面b)的的表項設為對映,因此在引起陷阱的指令重新啟動時,它將虛擬頁面b對映為實體地址頁框1中的某個位址。

虛擬位址被分成虛擬頁號(高位址)和偏移量(低位址)兩部分。不同的劃分對應了不同的頁面大小。

虛擬頁號可作為頁表的索引,以找到該虛擬頁面對應的頁表項。由頁表項可以找到對應的頁框。然後把頁框號拼接到偏移量的高位端,以替換調虛擬頁號,形成送往記憶體的實體地址。

頁表的目的是把虛擬頁面對映為頁框,把虛擬位址中的虛擬頁面域替換成頁框域,從而形成實體地址(本篇部落格討論的情況均不涉及虛擬機器,每個虛擬機器都需要有自己的虛擬記憶體,因此頁表組織變得很複雜,包括影子頁表和巢狀頁表)。

在任何分頁系統中,都需要考慮兩個主要問題:

每次訪問記憶體都需要進行虛擬位址到實體地址的對映,每條指令進行一兩次或更多頁表訪問是必要的。如果執行一條指令需要1ns,頁表查詢必須在0.2ns之內完成,以避免對映成為乙個主要瓶頸。

現代計算機使用至少32位的虛擬位址。假設頁面大小為4kb,32位的位址空間將有100萬頁,那麼頁表必然有100萬條表項,而且每個程序都需要自己的頁表。64位位址空間簡直多到超乎你的想象。​

大多數程式總是對少量的頁面進行多次的訪問,只有很少的頁表項會被反覆讀取,而其他大的頁表項很少被訪問。利用這種特性有一種解決方案:為計算機設計乙個小型的硬體裝置,將虛擬位址直接對映到實體地址,而不必再訪問頁表。這種裝置稱為轉換檢測緩衝區(translation lookaside buffers,tlb),有時又稱為相聯儲存器快表。它通常在mmu中,包含少量的表項,在實際中很少會超過256個。每個表項記錄了乙個頁面的相關資訊,包括虛擬頁號、頁面的修改位、保護碼和該頁鎖對應的物理頁框,還有另外一位用來記錄這個表項是否有效(即是否在使用)。

tlb的工作過程:將乙個虛擬位址放入mmu中進行轉換時,硬體首先通過將該虛擬頁號與tlb中所有表項同時(並行)進行匹配,判斷虛擬頁面是否在其中。如果發現在,並且不違反保護碼,則將頁框號直接從tlb中取出而不必再訪問頁表。如果違反了保護碼,則會產生乙個保護錯誤,就像對頁表進行非法操作一樣。如果虛擬頁號不在tlb中,此時就會去進行正常的頁表查詢。接著從tlb中淘汰掉乙個表項,然後用找到的頁表項代替它。當乙個表項被清除除tlb時,將修改位複製到記憶體中的頁表項,而除了訪問位,其他的值不變。當頁表項中從頁表中裝入tlb中時,所有的值都來自記憶體。

現代許多的機器,幾乎所有的頁面管理都在軟體中實現。tlb被作業系統顯示地載入,當發生tlb訪問失效時,生成乙個tlb失效並將問題交給作業系統解決。系統找到該頁面,然後從tlb中刪除乙個項,接著裝載乙個新的項,最後再執行先前出錯的指令。tlb失效比缺頁中斷更加頻繁。

如果tlb大到(如64個表項)可以減少失效率時,tlb的軟體管理就會變得足夠有效。

在減少tlb失效的同時,又要在發生tlb失效時減少處理開銷。有時候作業系統能用「直覺」指出哪些頁面下一步可能會被用到並預先為它們在tlb中裝載表項。

(軟體、硬體)處理tlb失效常用的辦法都是找到頁表並執行索引操作以定位將要訪問的頁面。軟體做這樣的搜尋時,通過在記憶體中的固定位置維護乙個大的(如4kb)tlb表項的軟體快取記憶體(該快取記憶體的頁面一直儲存在tlb中)來減少tlb失效。

兩種不同的tlb失效:

怎樣解決巨大的虛擬位址空間?兩種辦法

32位的虛擬位址被劃分為10位的pt1域,10位的pt2域和12位的offset(偏移量)域。因為偏移量是12位,所以頁面大小是4kb,共有220個頁面。假設每個程序都占用了4g的線性位址空間,頁表共含1m個表項,每個表項佔4個位元組,那麼每個程序的頁表要佔據4m的記憶體空間。為了節省頁表占用的空間,我們使用兩級頁表。每個程序都會被分配乙個頁目錄,但是只有被實際使用頁表才會被分配到記憶體裡面。一級頁表需要一次分配所有頁表空間,兩級頁表則可以在需要的時候再分配頁表空間。

引入多級頁表的原因是避免把全部頁表一直儲存在記憶體中(特別是一些從不需要的頁表)。

可以用以下命令檢視系統頁表大小:

getconf page_size
inux的頁表分配是根據cpu來設計的,不同平台(cpu)分頁不同.

x86平台使用二級頁表,可表示4gb的大小

x86_amd平台使用四級頁表,實際用來定址的只有48位(9,9,9,9,12)

目前來說四級頁表夠用,如果不夠用就擴充套件

此處講解二級頁表:

在左邊的是頂級頁表(頁目錄表),它有1024個表項,對應於10位的pt1域。當乙個虛擬位址被送到mmu時,mmu首先提取pt1域並把該值作為訪問頂級頁表的索引。因為整個4gb(即32位)虛擬位址空間已經按4kb大小分塊,所以頂級頁表中這1024個表項的每乙個都表示4m的塊位址範圍。二級頁表的每一項都表示4kb的位址範圍。offset對4096個位址進行編址。

由索引頂級頁表得到的表項中含有二級頁表的位址或頁框號。頂級頁表的表項0指向程式正文的頁表,表項1指向資料的頁表,表項1023指向堆疊的頁表,其他的表項未用,現在把pt2域作為訪問選定的二級頁表的索引,以便找到該虛擬頁面的對應頁框號。

雖然虛擬位址空間超過100萬個頁面,實際上只需要4個頁表:頂級頁表,0-4m(正文段),4m-8m(資料段)和頂端4m(堆疊段)的二級頁表。頂級頁表中1021個表項的「在/不在」都設成0,當訪問他們時強制產生乙個缺頁中斷。

二級頁表可擴充為**、四級或更多級。級數越多,靈活性就越大。

頁目錄指標表。每一級的頁表項由32位擴充套件到了64位,這樣處理器就能定址到4gb以外的位址空間。

虛擬記憶體,對映,分頁機制

這是我找到的關於虛擬記憶體和分頁機制的我個人比較容易理解的一篇文章。虛擬儲存器的思想是程式 資料和堆疊的大小都有可能超過物理記憶體大小,由作業系統把當前使用的放在記憶體,而不需要的放在磁碟。而絕大部分作業系統使用的虛擬儲存器技術就是分頁技術。在虛擬儲存器中,程式所產生的位址為虛擬位址,虛擬位址構成了...

虛擬記憶體,對映,分頁機制

這是我找到的關於虛擬記憶體和分頁機制的我個人比較容易理解的一篇文章。虛擬儲存器的思想是程式 資料和堆疊的大小都有可能超過物理記憶體大小,由作業系統把當前使用的放在記憶體,而不需要的放在磁碟。而絕大部分作業系統使用的虛擬儲存器技術就是分頁技術。在虛擬儲存器中,程式所產生的位址為虛擬位址,虛擬位址構成了...

記憶體分段 記憶體分頁 虛擬記憶體

程式通過鏈結器,多個檔案合併成乙個最終可執行檔案。可執行程式載入後占用的記憶體空間應該是連續的,因為執行指令的時候,程式計數器是順序地一條一條指令執行下去。這也就意味著,這一條條指令需要連續地儲存在一起。我們電腦肯定是要執行好多個程式的,在記憶體裡面肯定占用多個連續的分段,但是假如其中乙個程式退出,...