非連續分配容許一個程序分散地裝入到不相鄰的內存分區中,根據分區的大小是否固定分爲分頁存儲管理方式和分段存儲管理方式。程序員
固定分區會產生內部碎片,動態分區會產生外部碎片,這兩種技術對內存的利用率都比較低。咱們但願內存的使用能儘可能避免碎片的產生,這就引入了分頁的思想:把主存空間劃分爲大小相等且固定的塊,塊相對較小,做爲主存的基本單位。每一個進程也以塊爲單位進行劃分,進程在執行時,以塊爲單位逐個申請主存中的塊空間。
分頁的方法從形式上看,像分區相等的固定分區技術,分頁管理不會產生外部碎片。但它又有本質的不一樣點:塊的大小相對分區要小不少,並且進程也按照塊進行劃分,進程運行時按塊申請主存可用空間並執行。這樣,進程只會在爲最後一個不完整的塊申請一個主存塊空間時,才產生主存碎片,因此儘管會產生內部碎片,可是這種碎片相對於進程來講也是很小的,每一個進程平均只產生半個塊大小的內部碎片(也稱頁內碎片)。算法
①頁面和頁面大小。進程中的塊稱爲頁(Page),內存中的塊稱爲頁框(Page Frame,或頁幀)。外存也以一樣的單位進行劃分,直接稱爲塊(Block)。進程在執行時須要申請主存空間,就是要爲每一個頁面分配主存中的可用頁框,這就產生了頁和頁框的一一對應。
爲方便地址轉換,頁面大小應是2的整數冪。同時頁面大小應該適中,若是頁面過小,會使進程的頁面數過多,這樣頁表就過長,佔用大量內存,並且也會增長硬件地址轉換的開銷,下降頁面換入/換出的效率;頁面過大又會使頁內碎片增大,下降內存的利用率。因此頁面的大小應該適中,考慮到耷間效率和時間效率的權衡。
②地址結構。分頁存儲管理的邏輯地址結構如圖1所示。
編程
地址結構包含兩部分:前一部分爲頁號P,後一部分爲頁內偏移量W。地址長度爲32 位,其中0~11位爲頁內地址,即每頁大小爲4KB;12~31位爲頁號,地址空間最多容許有220頁。
③頁表。爲了便於在內存中找到進程的每一個頁面所對應的物理塊,系統爲每一個進程創建一張頁表,記錄頁面在內存中對應的物理塊號,頁表通常存放在內存中。
在配置了頁表後,進程執行時,經過查找該表,便可找到每頁在內存中的物理塊號。可見,頁表的做用是實現從頁號到物理塊號的地址映射,如圖2所示。
緩存
地址變換機構的任務是將邏輯地址轉換爲內存中物理地址,地址變換是藉助於頁表實現的。圖3給出了分頁存儲管理系統中的地址變換機構。
性能
在系統中一般設置一個頁表寄存器(PTR),存放頁表在內存的始址F和頁表長度M。進程未執行時,頁表的始址和長度存放在進程控制塊中,當進程執行時,纔將頁表始址和長度存入頁表寄存器。設頁面大小爲L,邏輯地址A到物理地址E的變換過程以下:操作系統
以上整個地址變換過程均是由硬件自動完成的。
例如,若頁面大小L爲1K字節,頁號2對應的物理塊爲b=8,計算邏輯地址A=2500 的物理地址E的過程以下:P=2500/1K=2,W=2500%1K=452,查找獲得頁號2對應的物理塊的塊號爲 8,E=8*1024+452=8644。
下面討論分頁管理方式存在的兩個主要問題:設計
由上面介紹的地址變換過程可知,若頁表所有放在內存中,則存取一個數據或一條指令至少要訪問兩次內存:一次是訪問頁表,肯定所存取的數據或指令的物理地址,第二次才根據該地址存取數據或指令。顯然,這種方法比一般執行指令的速度慢了一半。
爲此,在地址變換機構中增設了一個具備並行查找能力的高速緩衝存儲器——快表,又稱聯想寄存器(TLB),用來存放當前訪問的若干頁表項,以加速地址變換的過程。與此對應,主存中的頁表也常稱爲慢表,配有快表的地址變換機構如圖4所示。
blog
在具備快表的分頁機制中,地址的變換過程:索引
注意:有些處理機設計爲快表和慢表同時查找,若是在快表中查找成功則終止慢表的查找。
通常快表的命中率能夠達到90%以上,這樣,分頁帶來的速度損失就下降到10%如下。快表的有效性是基於著名的局部性原理。進程
第二個問題:因爲引入了分頁管理,進程在執行時不須要將全部頁調入內存頁框中,而只要將保存有映射關係的頁表調入內存中便可。可是咱們仍然須要考慮頁表的大小。以32 位邏輯地址空間、頁面大小4KB、頁表項大小4B爲例,若要實現進程對所有邏輯地址空間的映射,則每一個進程須要220,約100萬個頁表項。也就是說,每一個進程僅頁表這一項就須要4MB主存空間,這顯然是不切實際的。而即使不考慮對所有邏輯地址空間進行映射的狀況,一個邏輯地址空間稍大的進程,其頁表大小也多是過大的。以一個40MB的進程爲例,頁表項共40KB,若是將全部頁表項內容保存在內存中,那麼須要10個內存頁框來保存整個頁表。整個進程大小約爲1萬個頁面,而實際執行時只須要幾十個頁面進入內存頁框就能夠運行,但若是要求10個頁面大小的頁表必須所有進入內存,這相對實際執行時的幾十個進程頁面的大小來講,確定是下降了內存利用率的;從另外一方面來講,這10頁的頁表項也並不須要同時保存在內存中,由於大多數狀況下,映射所須要的頁表項都在頁表的同一個頁面中。
將頁表映射的思想進一步延伸,就能夠獲得二級分頁:將頁表的10頁空間也進行地址映射,創建上一級頁表,用於存儲頁表的映射關係。這裏對頁表的10個頁面進行映射只須要10個頁表項,因此上一級頁表只須要1頁就足夠(能夠存儲210=1024個頁表項)。在進程執行時,只須要將這1頁的上一級頁表調入內存便可,進程的頁表和進程自己的頁面,能夠在後面的執行中再i周入內存。
如圖5所示,這是Intel處理器80x86系列的硬件分頁的地址轉換過程。在32位系統中,所有32位邏輯地址空間能夠分爲220(4GB/4KB)個頁面。這些頁面能夠再進一步創建頂級頁表,須要210個頂級頁表項進行索引,這正好是一頁的大小,因此創建二級頁表便可。
舉例,32位系統中進程分頁的工做過程:假定內核已經給一個正在運行的進程分配的邏輯地址空間是0x20000000到0x2003FFFF,這個空間由64個頁面組成。在進程運行時,咱們不須要知道所有這些頁的頁框的物理地址,極可能其中不少頁還不在主存中。這裏咱們只注意在進程運行到某一頁時,硬件是如何計算獲得這一頁的頁框的物理地址便可。如今進程須要讀邏輯地址0x20021406中的字節內容,這個邏輯地址按以下進行處理:
邏輯地址: 0x20021406 (0010 0000 0000 0010 0001 0100 0000 0110 B)
頂級頁表字段:0x80 (00 1000 0000 B)
二級頁表字段:0x21 (00 0010 0001B)
頁內偏移量字段:0x406 (0100 0000 0110 B)
頂級頁表字段的0x80用於選擇頂級頁表的第0x80表項,此表項指向和該進程的頁相關的二級頁表;二級頁表字段0x21用於選擇二級頁表的第0x21表項,此表項指向包含所需頁的頁框;最後的頁內偏移量字段0x406用於在目標頁框中讀取偏移量爲0x406中的字節。
這是32位系統下比較實際的一個例子。看似較爲複雜的例子,有助於比較深刻地理解,但願讀者能本身動手計算一遍轉換過程。
創建多級頁表的目的在於創建索引,這樣不用浪費主存空間去存儲無用的頁表項,也不用盲目地順序式查找頁表項,而創建索引的要求是最高一級頁表項不超過一頁的大小。在 64位操做系統中,頁表的劃分則須要從新考慮,這是不少教材和輔導書中的常見題目,可是不少都給出了錯誤的分析,須要注意。
咱們假設仍然釆用4KB頁面大小。偏移量字段12位,假設頁表項大小爲8B。這樣,其上一級分頁時,每一個頁框只能存儲29(4KB/8B)個頁表項,而再也不是210個,因此上一級頁表字段爲9位。後面同理繼續分頁。64=12+9+9+9+9+9+7,因此需6級分頁才能實現索引。不少書中仍然按4B頁表項分析,雖然一樣得出6級分頁的結果,但顯然是錯誤的。這裏給出兩個實際的64位操做系統的分頁級別(注意:裏面沒有使用所有64位尋址,不過因爲地址字節對齊的設計考慮,仍然使用8B大小的頁表項),理解了表1中的分級方式,相信對多級分頁就很是清楚了。
平臺 | 頁面大小 | 尋址位數 | 分頁級數 | 具體分級 |
---|---|---|---|---|
Alpha | 8KB | 43 | 3 | 13+10+10+10 |
X86_64 | 4 KB | 48 | 4 | 12+9+9+9+9 |
分頁管理方式是從計算機的角度考慮設計的,以提升內存的利用率,提高計算機的性能, 且分頁經過硬件機制實現,對用戶徹底透明;而分段管理方式的提出則是考慮了用戶和程序員,以知足方便編程、信息保護和共享、動態增加及動態連接等多方面的須要。
段式管理方式按照用戶進程中的天然段劃分邏輯空間。例如,用戶進程由主程序、兩個子程序、棧和一段數據組成,因而能夠把這個用戶進程劃分爲5個段,每段從0開始編址,並分配一段連續的地址空間(段內要求連續,段間不要求連續,所以整個做業的地址空間是二維的)。其邏輯地址由段號S與段內偏移量W兩部分組成。
在圖6中,段號爲16位,段內偏移量爲16位,則一個做業最多可有216=65536個段,最大段長爲64KB。
在頁式系統中,邏輯地址的頁號和頁內偏移量對用戶是透明的,但在段式系統中,段號和段內偏移量必須由用戶顯示提供,在髙級程序設計語言中,這個工做由編譯程序完成。
每一個進程都有一張邏輯空間與內存空間映射的段表,其中每個段表項對應進程的一個段,段表項記錄該段在內存中的起始地址和段的長度。段表的內容如圖7所示。
在配置了段表後,執行中的進程可經過查找段表,找到每一個段所對應的內存區。可見,段表用於實現從邏輯段到物理內存區的映射,如圖8所示。
分段系統的地址變換過程如圖9所示。爲了實現進程從邏輯地址到物理地址的變換功能,在系統中設置了段表寄存器,用於存放段表始址F和段表長度M。其從邏輯地址A到物理地址E之間的地址變換過程以下:
在分段系統中,段的共享是經過兩個做業的段表中相應表項指向被共享的段的同一個物理副原本實現的。當一個做業正從共享段中讀取數據時,必須防止另外一個做業修改此共享段中的數據。不能修改的代碼稱爲純代碼或可重入代碼(它不屬於臨界資源),這樣的代碼和不能修改的數據是能夠共享的,而可修改的代碼和數據則不能共享。
與分頁管理相似,分段管理的保護方法主要有兩種:一種是存取控制保護,另外一種是地址越界保護。地址越界保護是利用段表寄存器中的段表長度與邏輯地址中的段號比較,若段號大於段表長度則產生越界中斷;再利用段表項中的段長和邏輯地址中的段內位移進行比較,若段內位移大於段長,也會產生越界中斷。
頁式存儲管理能有效地提升內存利用率,而分段存儲管理能反映程序的邏輯結構並有利於段的共享。若是將這兩種存儲管理方法結合起來,就造成了段頁式存儲管理方式。
在段頁式系統中,做業的地址空間首先被分紅若干個邏輯段,每段都有本身的段號,而後再將每一段分紅若干個大小固定的頁。對內存空間的管理仍然和分頁存儲管理同樣,將其分紅若干個和頁面大小相同的存儲塊,對內存的分配以存儲塊爲單位,如圖10所示。
在段頁式系統中,做業的邏輯地址分爲三部分:段號、頁號和頁內偏移量,如圖11 所示。
爲了實現地址變換,系統爲每一個進程創建一張段表,而每一個分段有一張頁表。段表表項中至少包括段號、頁表長度和頁表起始地址,頁表表項中至少包括頁號和塊號。此外,系統中還應有一個段表寄存器,指出做業的段表起始地址和段表長度。
注意:在一個進程中,段表只有一個,而頁表可能有多個。
在進行地址變換時,首先經過段表查到頁表起始地址,而後經過頁表找到頁幀號,最後造成物理地址。如圖12所示,進行一次訪問實際須要三次訪問主存,這裏一樣可使用快表以加快查找速度,其關鍵字由段號、頁號組成,值是對應的頁幀號和保護碼。