位址空間

在作業系統中,記憶體管理可讓您以多種方法將部分記憶體分配給程序,並在不再需要時釋出記憶體供日後重複使用。現代作業系統使用位址空間隔離程序記憶體。

位址空間代表程序用來參照記憶體的一組虛擬位址。虛擬地址會直接對應到實際地址。Fuchsia 使用 VMAR (虛擬記憶體位址區域) 來代表位址空間。

VMAR、對應和 VMO

在 Fuchsia 中,每個程序都有根層級 VMAR,且可分區為 VMAR 和對應階層。對應點到基礎 VMO (虛擬記憶體物件)

顯示根 VMAR、子項 VMAR、對應和 VMO

VMAR 和 VM 對應

VMAR 是特定程序位址空間中的連續虛擬位址範圍:

  • VMAR 可以為非重疊子區域含有子項 VMAR 和/或 VM 對應
  • 這些限制會將防護位元套用至記憶體部分 (讀寫、執行檔等)
  • 他們擁有子項的 WAVL 樹狀結構 可提高搜尋效率

VM 對應代表位址空間中的「對應」範圍,亦即由實體頁面支援的虛擬位址:

  • VM 對應沒有子項
  • 會對應 VMO 中的多個頁面
  • 成功的網頁搜尋結束於此

以下是可用的 VMAR 和 VM 對應 syscall:

另請參閱虛擬記憶體位址區域參考資料

VMOS

VMO 是記憶體的位元組容器。這類頁麵包含實體頁面,可透過 VM 對應功能對應到位址空間。以下是 VMO 系統呼叫:

另請參閱虛擬記憶體物件參考資料

虛擬記憶體管理工具 (VMM)

虛擬記憶體管理工具 (VMM) 負責維護程序位址空間,包括:

  • 提供指向對應虛擬位址範圍實體頁面的指標。
  • 請確認位址範圍已設定正確的存取防護位元。

方法是管理 VMAR、VM 對應、VMO 與硬體頁面資料表之間的關係。另請參閱 VMM 原始碼

程序開始時,其整個位址空間會表示為一個 VMAR。當位址空間的不同部分對應時,系統會填入 VMAR 階層樹狀結構。系統建立及刪除 VMAR 和 VM 對應時,會建立並刪除樹狀結構中的節點。

節點代表一個 VMAR 或 VM 對應:

  • VMAR 會指向子項清單,其中其他 VMAR 和 VM 對應位於父項 VMAR 的位址範圍內。
  • VM 對應會指向對應 VMO 中該位址範圍的範圍。

進一步瞭解如何透過根 VMAR 以視覺化方式呈現記憶體用量

VMM 使用隨機位址空間版面配置隨機化機制,控管在位址空間中建立新 VMAR 的位址範圍。 aslr.entropy_bits 核心指令列選項可用來控管隨機化的熵長度。熵越高,剖析器位址空間就會變得越來越分散。

實體記憶體管理工具 (PMM)

實體記憶體管理工具 (PMM) 會將系統中的所有可用實體記憶體 (RAM) 彙整為頁面,並管理相關情況。負責在需要時提供免費的實體頁面給 VMO。

VMO 是要求分頁,系統會視需求填入 (承諾) 頁面。網頁在寫入時就會認可。在此之前,未提交的頁面會以單例實體的零頁面呈現。避免需要為未存取或僅限讀取的頁面分配記憶體。

另外,使用者空間分頁器也能為 VMO 提供支援,該頁面會視需求填入 VMO 中的特定內容,例如從磁碟中的檔案讀取的內容。瞭解如何撰寫使用者呼叫器

範例:對應 VMO

如要對應 VMO:

  1. 請使用 zx_vmar_root_self() 取得程序根 VMAR 的控制代碼,例如:

    zx_handle_t vmar = zx_vmar_root_self();
    
  2. 使用 zx_vmo_create(...) 建立 VMO。這樣做會傳回 VMO 控制代碼,例如:

    const size_t map_size = zx_system_get_page_size();
    zx_vmo_create(map_size, 0, &vmo);
    
  3. 使用 zx_vmar_allocate(...) 在父項 VMAR 中建立子項 VMAR。系統會傳回 VMAR 控制代碼和其起始位址,例如:

    const size_t region_size = zx_system_get_page_size() * 10;
    zx_vmar_allocate(vmar, ZX_VM_CAN_MAP_READ | ZX_VM_CAN_MAP_WRITE, 0,
                     region_size, &region, &region_addr);
    

    這是選擇性步驟,您也可以直接將 VMO 對應至父項。

  4. 使用 zx_vmar_map(...) 對應 VMAR 中的 VMO。這會傳回現在對應至 VMAR 的 VMO 起始位址,例如:

    zx_vmar_map(region, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, vmo, 0,
                map_size, &map_addr);
    

顯示 VMO 與根層級 VMAR 的對應關係

範例:存取 VMO 對應

在上一個範例中,假設 zx_vmar_map() 傳回 map_addr 0x4000。如要存取對應的地址 0x4000,程式碼可能如下所示:

zx_vmar_map(...&addr); // addr = 0x4000
auto arr = reinterpret_cast<int*>(addr);
arr[0] = 1; // page fault

指標解除參照會導致頁面錯誤。如要解決頁面錯誤,核心會執行以下操作:

  1. 在從 root_vmar 開始,在程序的 VMAR 樹狀結構中搜尋位址 0x4000,直到找到包含該位址的 VM 對應為止。
  2. VM 對應會包含 VMO 參照,以及對應第一個位址的 VMO 頁面清單中的偏移值。查詢與位址 0x4000 對應的 VMO 偏移量。
  3. 如果 VMO 在該位移沒有頁面,請分配新的頁面。假設這個網頁的實際地址為 0xf000。
  4. 透過 ArchVmAspace,將虛擬位址 0x4000 轉譯為硬體頁面資料表 0xf000。該資料表代表用於追蹤 MMU 所用實體位址對應的架構專屬頁面資料表。

顯示 VMO 位址在 VMAR 位址範圍內