深入理解作業系統筆記 — 虛擬記憶體(Virtual Memory <VM>)

Whien
6 min readSep 3, 2021

|Virtual Memory 提供的優勢

虛擬記憶體作為緩存工具

將主記憶體當作是「儲存在磁碟上的地址空間」的高速緩存,在主記憶體中只保存活動區域,根據需要在磁碟與主記憶體之間來回傳送數據。

虛擬記憶體作為記憶體管理的工具

讓每個程序提供一致地址空間,簡化記憶體管理。

虛擬記憶體作為記憶體保護的工具

保護程序的地址空間不被其他程序破壞。

|專有名詞

  • 物理地址(Physical Address <PA>)
  • 物理尋址(Physical addressing)
  • 虛擬地址(Virtual Address <VA>)
  • 虛擬尋址(Virtual addressing)
  • 地址翻譯(address translation)

虛擬地址翻譯需要 CPU 與作業系統的結合,CPU 有個記憶體管理單元(Memory Management Unit <MMU>)並透過作業系統存放在記憶體中的動態查詢表來動態翻譯虛擬地址。

  • 地址空間(address space)

一個非負整復的有序集合 {0, 1, 2 …},如果是連續的則稱為線性地址空間(linear address space),通常都假設是一個線性的。

在一個虛擬記憶體系統中, CPU 會從一個有 N=2**n 個地址的地址空間生成虛擬地址,這個空間稱為虛擬地址空間(virtual address space)。

虛擬地址空間 {0, 1, 2, …, N - 1}

一個地址空間大小是由最大地址所需的位數來描述,例如,一個包含 N = 2**n 個地址的虛擬地址空間就叫做一個 n 位地址空間。

一個系統還有一個物理地址空間(physical address space)對應系統中物理記憶體的 M 個字節。

物理地址空間 {0, 1, 2, …, M - 1},M 不一定是 2 的幂。

  • 位於 CPU 和記憶體之間的 L1, L2, L3 高速緩存稱為 SRAM
  • 虛擬記憶體的緩存稱為 DRAM

|虛擬記憶體作為緩存工具

每一個字節都會有一個唯一的虛擬地址,作為到數組的索引。

磁碟上的數組內容被緩存在記憶體中,磁碟上的數據會被分割成為,這些塊作為磁碟和記憶體之間的傳輸單元,VM 系統將虛擬記憶體分割為虛擬頁(Virtual Page <VP>)的大小固定的塊來處理這個問題。

|虛擬頁

每個虛擬頁大小為 P = 2**p 字節,虛擬頁面的集合分成三個不相交的子集

  • 未分配的:VM 系統還未分配的頁,未分配的塊沒有任何數據和它相關,不佔用任何磁碟空間。
  • 緩存的:當前已緩存在物理記憶體中的已分配頁
  • 未緩存的:尚未緩存在物理記憶體中的已分配頁

|物理頁

物理記憶體被分割為物理頁(Physical Page <PP>),大小為 P 字節;也可稱為頁幀(page frame)。

|頁表(page table)

頁表將虛擬頁映射到物理頁,每次地址翻譯將一個虛擬地址轉換為物理地址時,都會讀取頁表。作業系統負責維護頁表內容,以及磁碟與 DRAM 之間來回傳送頁。

頁表是頁表條目(Page Table Entry <PTE>)的數組,每個 PTE 是由一個有效位(valid bit)和一個 n 位地址字段組成。

有效位可以標示此虛擬頁是否有被緩存在 DRAM 中。

如果設置為有效位,地址字位就表示 DRAM 中相應的物理頁起始位置,物理頁中緩存了虛擬頁。

如果沒有設置有效位,包含一個空的地址,則表示此虛擬頁尚未被分配,否則這個地址就指向該虛擬頁在磁碟上的起始位置。

考題:虛擬地址大小 n 為 16,頁大小 P = 2**p 為 4K,則需要的 PTE 數量

答:(2 ** 16) / (4 * 1024) = 65536 / 4096 = 16 個 PTE

|局部性(locality)

局部性(locality)原則保證了在任意時刻,程序將趨向於在一個較小的活動頁面(active page)集合上工作,這個集合叫做工作集(working set)或是常駐集合(resident page)。

在初始開銷時,就將工作集頁面調度到記憶體中,後續引用時將導致命中,不會有額外的磁碟流量。

|抖動(thrashing)

通常程序只要有時間局部性,虛擬記憶體就能工作良好。但如果工作集的大小超出了物理記憶體大小,則會產生抖動(thrashing),頁面將必須不斷的換進換出。

|虛擬記憶體作為記憶體管理的工具

每個程序都有一個獨立的頁表,獨立的虛擬空間地址。

*多個虛擬頁面可以映射到同一個共享物理頁面上

|簡化鏈接

獨立的地址空間允許程序記憶體映像使用相同的基本格式,不管實際程式碼與數據實際存放在物理記憶體何處。

對於 Linux 來說都使用類似的記憶體格式,對於 64 位地址空間來說,程式碼會從虛擬地址 0x400000,數據段跟在程式碼之後,中間有一段符合要求的對齊空白。

棧佔據了用戶程序地址空間最高的部分,向下生長。

這樣的一致性簡化了鏈接器的設計和實現,允許鏈接器生成完全鏈接的可執行文件,這些可執行文件是獨立於物理記憶體中程式碼和數據的最終位置的。

|簡化載入

虛擬記憶體很容易向記憶體中載入可執行文件和共享對象文件。

*將一組連續的虛擬頁映射到任意一個文件中的任意位置的表示法稱為記憶體映射(memory mapping)。

|簡化共享

獨立的地址空間替作業系統提供了一個管理用戶程序與作業系統自身之間共享的一致機制,通常來說程序都有獨立的程式碼、數據、堆及棧區域,是不和其他程序共享的。

使用到相同核心程式碼時,可以透過不同程序中的虛擬頁面映射到相同的物理頁面中,例如 C 標準庫的程式碼。

|簡化記憶體分配

當用戶程序需要額外記憶體時(malloc),作業系統會分配適當的連續 k 個虛擬記憶體頁面,並將它們映射到物理記憶體中 k 個任意位置,物理記憶體不需要連續,只要隨機分散在物理記憶體中。

|虛擬記憶體作為記憶體保護的工具

現代電腦都必須替作業系統提供方式來控制對記憶體系統的訪問。

  • 不應該允許一個用戶程序修改它的只讀程式碼。
  • 不應該允許一個用戶程序讀或修改任何核心中的程式碼和數據結構。
  • 不應該允許一個用戶程序讀取另一個用戶程序的私有記憶體。
  • 不應該允許修改任何與其他程序共享的虛擬頁面,除非所有共享者允許這麼做(通過系統調用)。

PTE 可以添加額外許可位來控制對一個虛擬頁面內容的訪問,如果指令違反了許可位控制,則 CPU 會觸發故障保護,將控制權傳遞給一個核心中的異常處理程序。Linux shell 一般將這種報告為 ”段錯誤(segmentation fault)”

--

--

Whien

遨遊在硬體與軟體世界中,對於計算機一切事物都充滿好奇及熱情。