記憶體管理單元

<image>

記憶體管理單元（memory management unit，縮寫為MMU），有時稱作分頁記憶體管理單元（paged memory management unit，縮寫為PMMU）。它是一種負責處理中央處理器（CPU）的記憶體訪問請求的電腦硬體。它的功能包括虛擬地址到物理地址的轉換（即虛擬內存管理）、記憶體保護、中央處理器高速緩存的控制，在較為簡單的計算機體系結構中，負責總線的仲裁以及存儲體切換（bank switching，尤其是在8位的系統上）。

在現代系統中，程序通常使用可訪問電腦架構理論最大記憶體容量的地址，即32位或64位地址。MMU將各程序的地址映射到物理記憶體中相互獨立的區域，而物理記憶體的容量通常遠小於理論最大值。這一機製得以實現，是因為程序在任一時刻實際使用的記憶體量通常較為有限。

大多數現代作業系統（Operating System，OS）均與MMU協同工作，以提供虛擬內存（Virtual Memory，VM）支持。MMU以固定大小的存儲塊（稱為頁面或頁）為單位追蹤記憶體使用情況。若程序引用某個不在物理記憶體中的頁面位置，MMU將向作業系統發送中斷信號。作業系統隨即選擇一個使用頻率較低的記憶體塊，若該塊自載入後已被修改，則將其寫入後備存儲器（如硬碟），隨後從後備存儲器讀取所需頁面至該記憶體塊，並配置MMU將該記憶體塊映射至程序最初請求的頁面，以供程序使用。這一過程稱為請求分頁（Demand Paging）。部分較為簡單的實時作業系統（Real-Time Operating System，RTOS）不支持虛擬內存功能，因此無需MMU，但仍需配備硬體存儲保護單元（Memory Protection Unit）。

MMU通常提供存儲保護（Memory Protection）功能，阻止程序訪問其未曾申請的記憶體區域，從而防止行為異常或惡意的程序修改或讀取其他程序的數據。

在某些早期微處理器設計中，存儲管理功能由獨立的積體電路實現，例如VLSI Technology公司的VI475（1986年）、與Motorola 68020處理器配套用於Macintosh II電腦的Motorola 68851（1984年），以及與Zilog Z8000系列處理器配套使用的Z8010和Z8015（1985年）。後續微處理器（如Motorola 68030和Zilog Z280）將MMU與中央處理器集成於同一積體電路晶片上，Intel 80286及後續x86系列微處理器亦採用此設計。

## 工作機制

早期系統採用基址-界限尋址（Base and Bounds Addressing）技術，該技術進一步發展演變為分段（Segmentation）機制；亦有系統採用固定存儲塊集合，而非按需載入。這兩種方法的根本區別在於連續記憶體塊的大小：分頁系統（Paged Systems）將主存儲器劃分為一系列等尺寸的存儲塊，而分段系統（Segmented Systems）通常允許使用可變尺寸的存儲塊。

### 分段轉換

在分段轉換（Segmented Translation）機制中，記憶體地址由段號（Segment Number）和段內偏移量（Offset within the Segment）兩部分構成。段具有可變長度，並可關聯訪問權限屬性，如讀（Read）、寫（Write）和執行（Execute）權限。段被載入物理記憶體中的連續區域。通常，段號用作段表（Segment Table）的索引；段表中的每個條目包含該段所在物理記憶體區域的地址、段長度，以及權限標誌等其他資訊。

此種方式的優勢在於結構簡潔：由於記憶體塊連續，映射過程僅需存儲基址（Base）和界限（Limit）兩個數值即可。

該方法的缺陷在於會導致一種稱為外部碎片（External Fragmentation）的現象。當記憶體分配被釋放但釋放區域不連續時，便會產生外部碎片。此時，系統中可用記憶體總量雖足以滿足請求，但由於這些記憶體分散分布，無法分配給單個段使用。在程序頻繁啟動和終止的系統中，隨著時間推移，記憶體可能變得高度碎片化，導致不存在足夠大的連續塊；此時需將段在記憶體中移動，並修改其段表項以反映新的物理地址，從而騰出足夠大的連續空間以容納該段。

部分型號的 PDP-11 16位小型計算機配備分段存儲管理單元，具有一組頁面地址寄存器（Page Address Registers，PARs）和頁面描述寄存器（Page Description Registers，PDRs）；該機制將16位虛擬地址映射為18位物理地址。PDP-11/70 型號進一步擴展為22位物理地址。分段機制在1980年代的微型計算機平台上得到廣泛應用。採用此概念的MMU包括 Motorola 68451 和 Zilog Z8010，但亦存在諸多其他實例。

Intel 8086、Intel 8088、Intel 80186 及 Intel 80188 提供基礎的存儲分段功能，但不具備存儲保護機制。（每個段的每個字節始終對任何程序可見。）16位段寄存器支持65,536個段；每個段起始於固定偏移量，該偏移量等於段號乘以16；段起始地址粒度為16位元組。每個段允許對64 KiB（65,536位元組）的地址空間進行讀寫訪問（此限制由16位程序計數器PC和堆棧指針SP寄存器設定；處理器不進行邊界檢查）。偏移量與地址之和超過0xFFFFF時，將迴繞至0x00000。每個64 KiB段與後續4,095個段重疊；每個物理地址可由4,096組段-偏移量對表示。該方案僅能尋址1 MiB（1024 KiB）的物理記憶體（及記憶體映射I/O）。（可選的擴展記憶體硬體可在軟體控制下增加存儲體切換記憶體。）後續x86處理器自 Intel 80286 起支持真正的分段映射，並配備段表。

### 分頁轉換

在分頁轉換（Paged Translation）機制中，地址空間（即處理器使用的地址範圍）被劃分為若干頁面（Pages），每個頁面的大小為2的冪次方，通常為數千字節，但也可能更大。程序使用機器的自然地址大小引用記憶體，在現代系統中通常為32位或64位。地址的低位部分（即頁內偏移量）保持不變；高位部分則為虛擬頁號（Virtual Page Numbers）。

大多數MMU使用記憶體中的頁表（Page Table）作為條目列表，每個虛擬頁對應一個頁表項（Page Table Entry，PTE），用於將虛擬頁號映射到主存儲器中的物理頁號。為減少頁表尺寸，常採用多級頁表（Multi-Level Page Tables）。PTE的相聯緩存（Associative Cache）稱為轉譯檢測緩衝區（Translation Lookaside Buffer，TLB），用於避免每次映射虛擬地址時都訪問主存儲器。

其他MMU可能採用私有記憶體陣列、一組寄存器，或一層或多層靜態隨機存取存儲器（Static RAM）陣列來存儲映射資訊集合。

MMU將虛擬地址劃分為虛擬頁號和頁內偏移量。虛擬頁號用於選擇頁表項；若找到該頁表項，且頁面標記為在記憶體中，則將頁表項中的物理頁號與偏移量組合，構建對應於該虛擬地址的物理地址。

虛擬頁號可直接用作頁表或其他映射資訊的索引，亦可進一步劃分：某層地址位用作低級表索引，下一層地址位用作更低級表索引，形成兩層或更多層索引結構。

分頁轉換存在一個問題：隨著虛擬地址空間擴展，保存映射資訊所需的記憶體量亦隨之增加。例如，在68020處理器中，地址寬度為32位，若頁面大小為8 kB，則虛擬頁號為地址的高19位，單級頁表大小將達512 kB。在1980年代，對於記憶體中的頁表，這可能占機器主存儲器的相當比例；對於將頁映射存儲於靜態RAM的MMU，則可能需要大量昂貴的靜態RAM。此問題可通過增大頁面尺寸來緩解，例如由8 kB增至64 kB。此時頁索引使用16位，生成的頁表大小為64 kB，更為可行。然而，增大頁面尺寸會導致第二個問題：內部碎片（Internal Fragmentation）增加。若程序連續請求小塊記憶體，將被分配大塊記憶體，從而造成大量記憶體浪費。

若地址空間稀疏，即並非所有區域均已分配，則可通過使用多級頁表或靜態RAM映射來緩解該問題，且無需為空閒區域分配全部所需的頁表項。

分頁轉換方法在1970年代和1980年代的微處理器MMU中得到廣泛應用，包括68020的68851、68030的片上MMU、Zilog Z8000的Z8015，以及NS32000系列的NS16082。

頁表項或其他每頁資訊還可能包含以下資訊：頁面是否已被寫入（髒位，Dirty Bit）、上次使用時間（訪問位，Accessed Bit，用於最近最少使用（Least Recently Used，LRU）頁面置換演算法）、可讀寫該頁面的進程類型（使用者模式或管理模式），以及是否應緩存該頁面。

有時，頁表項或其他每頁資訊可能禁止訪問特定虛擬頁，原因可能是該虛擬頁未分配物理隨機存取存儲器（Random-Access Memory，RAM）。此時，MMU向CPU發出缺頁中斷（Page Fault）信號。作業系統隨即處理該情況，可能嘗試尋找空閒RAM幀並設置頁映射以將其映射至請求的虛擬地址。若無空閒RAM，則可能需要使用某種置換演算法選擇現有頁面（稱為犧牲頁，Victim），並將其保存至磁碟（此過程稱為頁面置換，Paging）。某些MMU可能出現PTE短缺，此時作業系統必須釋放一個PTE以建立新映射。

對於非法或不存在記憶體訪問，MMU還可能分別產生非法訪問錯誤（Illegal Access Error）條件或無效缺頁中斷（Invalid Page Fault），由作業系統處理時導致段錯誤（Segmentation Fault）或總線錯誤（Bus Error）。

分頁轉換緩解了記憶體外部碎片（External Fragmentation）問題。記憶體塊分配和釋放後，空閒記憶體可能變得碎片化（不連續），導致最大連續空閒塊遠小於空閒記憶體總量。藉助虛擬內存，連續的虛擬地址範圍可映射至若干不連續的物理記憶體塊；這種不連續分配是分頁的優勢之一。

然而，分頁轉換導致另一個問題——內部碎片。當程序請求的記憶體塊無法完整映射到頁面時，便會產生內部碎片。例如，若程序請求1 KB緩衝區用於文件操作，該請求將導致整個頁面被分配，儘管僅使用1 KB；若頁面大於1 KB，則頁面剩餘部分被浪費。若進行大量此類小塊分配，即使大量記憶體仍為空，記憶體也可能被耗盡。

### 分段與分頁結合

部分系統（如 GE 645 及其後繼機型）同時採用分段和分頁兩種機制。此類系統的段表（Segment Table）並非包含各段的條目（給出段的物理基址和長度），而是包含給出該段頁表物理基址的條目，同時保留段的長度資訊。物理記憶體被劃分為固定大小的頁面，純分頁機制中使用的請求分頁技術同樣適用於段頁結合的請求分頁機制。

Signetics 68905 MMU 專為 Motorola 68000、68010 及 68012 微處理器設計，支持分段和分頁功能。Signetics 和 Philips 均生產了將 68905 與處理器集成於同一物理晶片上的 68000 版本，即 68070。

### IOMMU

執行直接記憶體訪問（Direct Memory Access，DMA）的硬體完全繞過CPU的MMU。部分I/O系統允許DMA硬體使用物理地址（Physical Addresses）直接對物理RAM中的任意位置進行讀寫，且不受任何限制。其他I/O系統則配備獨立的MMU，稱為輸入輸出記憶體管理單元（Input-Output Memory Management Unit，IOMMU），可由作業系統編程配置，將DMA硬體發出的設備地址（Device Addresses）轉換為由作業系統指定的特定受限物理頁面。IOMMU可用於阻斷DMA攻擊（DMA Attacks）。

## 益處

MMU可提供存儲保護（Memory Protection）功能，使得代碼試圖訪問或修改其無權訪問的數據時操作失敗；該機制既能捕獲軟體缺陷，亦能阻止對數據的蓄意訪問或修改。通常，作業系統為每個程序分配獨立的虛擬地址空間（Virtual Address Space）而不會讓程序直接訪問物理記憶體。這種記憶體保護特性可以避免某個程序非法訪問其他程序的虛擬內存空間。有時候軟體自身的錯誤會引發頁錯誤，這時記憶體管理單元可以檢測到頁錯誤，然後通知作業系統終止出錯的程序。

當虛擬地址空間過小時，MMU亦可用於擴展物理地址空間的大小。例如，PDP-11 最初採用16位地址，隨著1970年代存儲器容量增長，該地址寬度逐漸不敷使用。對此，系統將物理存儲器總線擴展至18位，並利用MMU根據處理器總線上的其他引腳指示當前訪問存儲器的程序，從而添加兩個附加地址位。

此外，記憶體管理單元能夠減少程序的記憶體碎片化現象。也就是說，當程序分配並釋放記憶體塊後，可分配的連續記憶體塊的最大尺寸亦遠小於尚未分配的記憶體量。虛擬內存機制可以在記憶體分頁機制的基礎上，將多個不連續的物理記憶體區塊映射為一個連續的虛擬內存塊。