1. 程式人生 > >3.1.4.1 基本分頁儲存管理方式

3.1.4.1 基本分頁儲存管理方式

非連續分配允許一個程式分散地裝入到不相鄰的記憶體分割槽中,根據分割槽的大小是否固定分為分頁儲存管理方式和分段儲存管理方式。

分頁儲存管理方式中,又根據執行作業時是否要把作業的所有頁面都裝入記憶體才能執行分為基本分頁儲存管理方式和請求分頁儲存管理方式。

1、基本分頁儲存管理方式

固定分割槽會產生內部碎片,動態分割槽會產生外部碎片,這兩種技術對記憶體的利用率都比較低。我們希望記憶體的使用能儘量避免碎片的產生。這就引入了分頁的思想:把主存空間劃分為大小相等且固定的塊,塊相對較小,作為主存的基本單位。每個程序也以塊為單位進行劃分,程序在執行時,以塊為單位逐個申請主存中的塊空間。

分頁的方法從形式上看賣相分割槽相等的固定分割槽技術,分割槽管理不會產生外部碎片。但它又有本質的區別:塊的大小相對分割槽要小很多,而且程序也按照塊進行劃分,程序執行時按塊申請主存可用空間並執行。這樣,程序只會在為最後一個不完整的塊申請一個主存塊空間時,才產生主存碎片,所以儘管會產生內部碎片,但是這種碎片相對程序來說也是很小的,每個程序平均產生半個塊大小的內部碎片(也稱頁內碎片)

(1)分頁儲存的幾個基本概念

①頁面和頁面大小

程序中的塊稱為頁(Page),記憶體中的塊稱為頁框(Page Frame,或頁幀)。外存也以同樣的單位進行劃分,直接稱為塊(Block)。程序在執行時需要申請主存空間,就是要為每個頁面分配主存中的可用頁框,這就產生了頁和頁框的一一對應。

為方便地址轉換,頁面大小應是2的整數冪。同時頁面大小應該適中。如果頁面太小,會使程序中的頁面過多,這樣頁表就過長,佔用大量記憶體,而且會增加硬體地址轉換的開銷,降低頁面換入換出的效率;頁面過大又會使頁內碎片增大,降低記憶體的利用率。所以頁面的大小應該適中,考慮到記憶體效率和時間效率的權衡。

②地址結構。分頁儲存管理的邏輯地址結構:

31...12 11...0
頁號P 頁內偏移量
地址結構包含兩部分:前一部分為頁號P,後一部分為頁內偏移量W。地址長度為32位,其中0-11位為頁內地址,即每頁大小為4KB;12-31位為頁號,地址空間最多允許有2^20頁。

③頁表。為了便於在記憶體中找到程序的每個頁面所對應的物理塊,系統為每個程序建立一張頁表,記錄頁面在記憶體中對應的物理號,頁表 一般存放在記憶體中。

在配置了頁表後,程序執行時通過查詢該表,即可找到每頁在記憶體中的物理塊號。可見,頁表的作用是實現頁號到物理塊號的地址對映。

(2)基本地址的變換機構

地址變換機構的任務是將邏輯地址轉換為記憶體中實體地址,地址變換是藉助於頁表實現的。

在系統中通常設定一個頁表暫存器(PTR),存放頁表在記憶體的始址F和頁表長度M,程序未執行時,頁表的始址和長度存放在程序控制塊中,當程序執行時,才將頁表始址和長度存入頁表暫存器。設頁面大小為L,邏輯地址A到實體地址E的變換過程如下:

①計算頁號P(P=A/L)和頁內偏移量W(w=A%L)

②比較頁號P和頁表長度M,若P>=M,則產生越界中斷,否則繼續執行。

③頁表中P對應的頁表項地址=頁表起始地址F+頁號*頁表項長度,取出該頁表項內容b,即為物理塊號。

④計算E=b*L+W

以上整個地址變換過程均是由硬體自動完成的。

假如,頁面大小L為1K位元組,頁號2對應的物理塊為b=8,計算邏輯地址A=2500的實體地址 E的過程如下

p=2500/1K=2;

w=2500%1K=452;

查詢得到頁號2對應的物理塊的塊號為8,E=8*1024+452=8644.

下面討論分頁管理方式存在的兩個主要問題:

①每次訪存操作都需要進行邏輯地址到實體地址的轉換,地址轉換過程必須足夠快,否則訪存速度會降低。

②每個程序引入了頁表,用於儲存對映機制,頁表不能太大,否則記憶體利用率會降低。

(3)具有快表的地址變換機構 

由上面介紹的地址變換過程可知。若頁表全部放在記憶體中,則存取一個數據或一條指令至少要訪問兩次記憶體

第一次是訪問頁表,確定所存取的資料或指令的實體地址

第二次才根據該地址存取資料或指令。

顯然,這種方法比通常執行指令的速度慢了一半。

為此,在地址變換機構中增設了一個具有並行查詢能力的快取記憶體儲存器——塊表,又稱為聯想暫存器(TLB),用來存放當前訪問的若干頁表項,以加速地址變換的過程。於此對應,主存中的頁表也常稱為慢表。

在具有快表的分頁機制中,地址的變換過程:

①CPU給出邏輯地址後,由硬體地址進行地址轉換並將頁號送入高速地址緩衝暫存器,並將此頁號與快表中的所有頁號進行比較。

②如果找到匹配的頁號, 說明所要訪問的頁表項在塊表中,則直接從中取出該頁所對應的頁框號,與頁內偏移量拼接成實體地址。這樣存取資料僅一次訪存便可實現。

③如果沒有找到,則需要訪問主存中的頁表,在讀出頁表項後,應同時將其存入快表,以便後面可能的再次訪問。但若快表已滿,則必須按照一定的演算法對舊的頁表進行替換。

注意:有些處理機設計為塊表和慢表同時查詢,如果在塊表中查詢成功則終止慢表的查詢。

一般塊表的命中率可以達到90%以上,這樣,分頁帶來的速度損失降低到10%以下。快表的有效性是基於區域性性原理。這在後面的虛擬記憶體中將具體討論。

(4)兩級頁表

第二個問題:由於引入了分頁管理,程序在執行時不需要將所有頁調入記憶體頁框中,而只要將儲存有對映關係的頁表調入記憶體即可。但是我們仍然需要考慮頁表的大小。以32位邏輯空間,頁面大小4KB,頁表項大小4B為例,若要實現程序對全部邏輯空間的對映,則每個程序需要(2^32/4KB)2^20,約100萬個頁表項。也就是說,每個程序僅頁表這一項就需要4MB主存空間,這顯然是不切合實際的。

而即便不考慮對全部邏輯地址空間進行對映的情況,一個邏輯地址空間稍大的程序,其頁表大小也可能是過大的。

①程序舉例(全部放入記憶體)

以一個40MB的程序為例,頁表項共40KB(40MB/4KB*4B),如果將所有頁表項內容儲存在記憶體中,那麼需要(40KB/4KB)10個記憶體頁框來把儲存整個頁表。整個程序大小約為(40MB/4KB)1萬個頁面,而實際執行時只需要幾十個頁面進入記憶體頁框就可以執行,但如果要求10個頁面大小的頁表必須全部進入記憶體,這相對實際執行的幾十個程序頁面的大小來說,肯定是降低了記憶體利用率的;從另一方面來講,這10頁的頁表項也並不需要同時儲存在記憶體中,因為大多數情況下,對映所需要的頁表項都在頁表的同一頁面中。

解決方案:

為了壓縮頁表,我們將頁表對映的思想進一步延伸,就可以得到二級分頁,即使用層次結構的頁表:將頁表的10頁空間也進行地址對映,建立上一級頁表,用於儲存頁表的對映關係。這裡對頁表的10個頁面進行對映只需要10個頁表項,所以上一級頁表只需要1頁就足夠(可以儲存2^10=1024個頁表項)。在程序執行時,只需要將1頁的上一級頁表調入記憶體即可,程序的頁表和程序本身的頁面,可以在後面的執行中再調入記憶體。

②系統舉例(頁表理論佔用最大記憶體)

以上面提到的條件:32位邏輯地址空間、頁面大小4kB、頁表項大小4B,以位元組為編址單位,我們就這個條件來構造一個合適這個條件的頁表結構。頁面大小為4KB,則頁內偏移址為log2 4K=12位,頁號部分為20位,若不採用分級頁表,那麼光頁表就要佔用2^20*4B/4KB=1024頁(頁框),而這大大超過了許多程序自身需要的頁面,對於記憶體來說是非常浪費資源的,而且查詢頁表工作也變得十分不便,試想若把這些頁表放在連續的空間中,查詢對應的物理頁號的時候可以通過頁表首頁地址+頁號*4B的形式得到,而這種方法查詢起來雖然相對方便,但是連續的1024頁對於記憶體的要求實在太高,並且上面說到了其中大多數頁面都是不會用到的,所以這種方法並不具有可行性。

解決方案:

如果不把這些頁表放在連續的空間中,我們就需要一張索引表來告訴我們第幾張應該去哪找,這就能解決頁表的查詢問題,並且不用把所有的頁表都調入記憶體,只有需要它的時候才調入(虛擬儲存器思想),這就能解決佔用記憶體空間過大的問題。

你也許會發現了這個方案和當初引進頁表機制的方式一模一樣,實際上就是構建一個頁表的頁表,也就是二級頁表。為了查詢的方便,頂級頁表大小設立一個頁面,那麼頂級頁表共可以容納4KB/4B=1K個頁表項,則它佔用的地址位數為log2 1K=10位,而之前計算過頁內偏移地址佔用了12位,那麼32位的邏輯地址空間就剩下10位,正好使得二級頁表的大小在一頁之內,這樣我們就得到了路基地址空間的格式:

一級頁號 二級頁號 頁內偏移

二級頁表實際上就是在原有頁表結構上再加了一層頁表

建立多級頁表的目的在於建立索引,這樣不用浪費主存空間去儲存無用的頁表項,也不用盲目地順序式查詢頁表項,而建立索引的要求是最高一級頁表項不超過一頁的大小。