虛擬記憶體位址區域

NAME

vm_address_region - 虛擬記憶體位址空間的連續區域

概要

虛擬記憶體位址區域 (VMAR) 代表虛擬位址空間的連續部分。

說明

核心和使用者空間會使用 VMAR 來表示位址空間的分配。

每個程序一開始都會有一個跨越整個位址空間的 VMAR (根 VMAR),請參閱 zx_process_create()。每個 VMAR 都可以按照邏輯分割成任意數量的不重疊部分,每個各代表一個子項 VMAR、虛擬記憶體對應或缺口。子項 VMAR 是使用 zx_vmar_allocate() 建立。VM 對應是使用 zx_vmar_map() 建立。

VMAR 採用階層式權限模型,可授予對應的對應權限。舉例來說,根 VMAR 允許讀取、寫入,以及可執行的對應。可以建立只允許讀取及寫入對應的子項 VMAR,在這種情況下,建立允許執行檔對應的子項是違法行為。

使用 zx_vmar_allocate() 建立 VMAR 時,其父項 VMAR 會保留對其的參照。因此,如果對子項 VMAR 的所有控點關閉,子項及其子系在位址空間中仍會繼續運作。如要中斷子項與位址空間的連線,您必須對子項的控制代碼呼叫 zx_vmar_destroy()

根據預設,系統會隨機分配所有位址空間。在建立 VMAR 時,呼叫端可選擇要使用的隨機演算法。預設配置器會嘗試在 VMAR 的完整寬度上廣泛分配配置。使用 ZX_VM_COMPACT 選取的替代分配器會嘗試在 VMAR 內保持鄰近位置,但位於範圍內的隨機位置。建議使用預設分配器。

VMAR 可選擇支援固定偏移對應模式 (稱為特定對應)。這個模式可用於建立保護頁面,或是確保對應的相對位置。無論其父項 VMAR 是否具有該權限,每個 VMAR 都可能具有 ZX_VM_CAN_MAP_SPECIFIC 權限。

範例

#include <zircon/syscalls.h>

/* Map this VMO into the given VMAR, with |before| bytes of unmapped guard space
   before it and |after| bytes after it.  */
zx_status_t map_with_guard(zx_handle_t vmar, size_t before, size_t after,
                           zx_handle_t vmo, uint64_t vmo_offset,
                           size_t mapping_len, uintptr_t* mapped_addr,
                           zx_handle_t* wrapping_vmar) {

    /* wrap around check elided */
    const size_t child_vmar_size = before + after + mapping_len;
    const zx_vm_option_t child_vmar_options = ZX_VM_CAN_MAP_READ |
                                              ZX_VM_CAN_MAP_WRITE |
                                              ZX_VM_CAN_MAP_SPECIFIC;
    const zx_vm_option_t mapping_options = ZX_VM_SPECIFIC |
                                           ZX_VM_PERM_READ |
                                           ZX_VM_PERM_WRITE;

    uintptr_t child_vmar_addr;
    zx_handle_t child_vmar;
    zx_status_t status = zx_vmar_allocate(vmar, child_vmar_options, 0,
                                          child_vmar_size,
                                          &child_vmar,
                                          &child_vmar_addr);
    if (status != ZX_OK) {
        return status;
    }

    status = zx_vmar_map(child_vmar, mapping_options, before, vmo, vmo_offset,
                         mapping_len, mapped_addr);
    if (status != ZX_OK) {
        zx_vmar_destroy(child_vmar);
        zx_handle_close(child_vmar);
        return status;
    }

    *wrapping_vmar = child_vmar;
    return ZX_OK;
}

另查看

音效