RFC-0013:複製 VMO 對應 | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 系統呼叫,可從對應建立 VMO 的 CoW 複本,而不需要對應的句柄。 |
問題 | |
Gerrit 變更 | |
作者 | |
審查人員 | |
提交日期 (年-月-日) | 2020-10-26 |
審查日期 (年-月-日) | 2020-12-09 |
摘要
目前只有在您擁有 VMO 的句柄時,才能建立 CoW 的複本。這對於 zygote 用途來說並不足夠,因為 CoW 需要複製整個位址空間,包括已關閉所有 VMO 句柄的對應項目。本 RFC 提出了新的系統呼叫,以解決這個差距。
動機和問題陳述
Linux 上的 Chromium 會從 zygote 程序分支轉譯器,藉此產生轉譯器,進而大幅節省記憶體和 CPU 用量。我們希望在 Fuchsia 上實現這些節省。
為此,我們需要實作「位址空間複製」作業的某種方式,在提供以下資訊時:
- 程序根 VMAR
- 部分參照在位址空間中對應的 VMOs 的句柄
會傳回:
- 新的程序,其位址空間由輸入程序中對應的 VMOs 複本填入
- 針對輸入程序中參照 VMO 的每個句柄,新程序中參照該 VMO 對應複本的新句柄
只要新增這個系統呼叫,我們就能輕鬆在使用者空間中實作這項功能。這項作業會透過 ZX_INFO_PROCESS_MAPS
取得位址空間版面配置,並使用 zx_vmar_create_vmo_child
建立每個對應項目的複本,但會排除任何有句柄的 VMOs,因為這些會透過 zx_vmo_create_child
處理。
設計
zx_vmar_create_vmo_child
zx_status_t zx_vmar_create_vmo_child(zx_handle_t handle,
uint32_t options,
zx_vaddr_t addr,
size_t size,
zx_handle_t* out)
為 handle
參照的 VMAR 中,在 addr
到 addr
+size
範圍內對應的頁面建立 CoW 複本。範圍必須是單一 VMO 對應項目的子範圍,也就是說,範圍不得跨越兩個對應項目,也不能包含任何未對應的頁面。結果是新的 VMO,是範圍中對應的 VMO 的子項。
允許的選項為 ZX_VMO_CHILD_SNAPSHOT
、ZX_VMO_CHILD_SNAPSHOT_AT_LEAST_ON_WRITE
和 ZX_VMO_CHILD_NO_WRITE
。解讀方式與 zx_vmo_create_child
相同。(ZX_VMO_CHILD_SLICE
目前不允許使用,因為安全性問題:必須特別小心,確保修改父項 VMO 的功能不會破壞任何安全性界線)。
如果符合下列情況,就會傳回 ZX_ERR_INVALID_ARGS
:
- 範圍
addr
到addr
+size
並非單一 VMO 對應項目的子範圍 addr
或size
未對齊頁面
如果符合下列情況,就會傳回 ZX_ERR_ACCESS_DENIED
:
- 對應是使用新的標記
ZX_VM_CANNOT_CREATE_VMO_CHILD
完成,或是 vmar 選項包含此標記 handle
沒有ZX_RIGHT_INSPECT
如果 handle
不是有效的句柄,則會傳回 ZX_ERR_BAD_HANDLE
;如果 handle
不是 VMAR,則會傳回 ZX_ERR_WRONG_TYPE
;如果 VMAR 已遭到銷毀,則會傳回 ZX_ERR_BAD_STATE
。如果符合說明中的情況,也可以傳回 zx_vmo_create_child
傳回的任何錯誤。
傳回的 VMO 句柄將包含 ZX_DEFAULT_VMO_RIGHTS
,並且會進行以下變更:
- 如果指定
ZX_VMO_CHILD_NO_WRITE
,系統就會移除ZX_RIGHT_WRITE
。 - 如果對應項目可執行,且未指定
ZX_VMO_CHILD_NO_WRITE
,系統會新增ZX_RIGHT_EXECUTE
。也就是說,您可以建立可執行對應項目的可執行複本,但必須是唯讀。
ZX_VM_CANNOT_CREATE_VMO_CHILD
ZX_VM_CANNOT_CREATE_VMO_CHILD
是新的 zx_vm_options_t
標記,可用於指定 VMO 對應或 VMAR。這可讓對應 VMO 或建立 VMAR 的程式碼禁止在這些項目上使用 zx_vmar_create_vmo_child
。
實作
新增系統呼叫並非複雜的變更,可在一個 CL 中完成。複製演算法的實作方式不在本 RFC 的討論範圍內。
成效
由於此系統呼叫只能用於 zygote 實作內容,因此不值得單獨對其進行基準測試。我們應該評估 zygote 實作項目的整體效能。
安全性考量
目前無法使用 VMAR 參照值 (而非句柄) 建立 VMO 子項,但這項 RFC 可讓您這麼做。這有點像是憑空授予新能力。
在這種情況下,由於最終結果與先前建立新 VMO 並複製資料 (但使用較少記憶體) 相同,因此風險似乎不高。如果需要禁止這項功能,本 RFC 建議可使用的 zx_vm_options_t
標記 (ZX_VM_CANNOT_CREATE_VMO_CHILD
)。
測試
系統會對系統呼叫進行單元測試。針對未來實作位址空間複製功能的測試,也會做為系統呼叫的整合測試。
說明文件
這份 RFC 是 zx_vmar_create_vmo_child
說明文件的起點。
缺點、替代方案和未知事項
還有哪些策略可以解決同樣的問題?
我們可以新增系統呼叫,執行整個位址空間複製作業。無論是介面還是實作方式,這都會是相當複雜的系統呼叫。將複雜性推送至使用者空間會是較好的做法。
我們可以新增系統呼叫,允許從對應中鑄造 VMO 句柄。這可讓您實作 zx_vmar_create_vmo_child
的使用者空間,方法是先從對應建立句柄,然後呼叫 zx_vmo_create_child
。不過,Zircon API 通常只允許為新建立的物件鑄造控制代碼,以便讓介面更容易推理。這個系統呼叫必須從空白中建立句柄。
您可以使用各種技巧來避免關閉任何 VMO 句柄,例如修改所有建立及對應 VMOs 的程式碼,以免關閉這些 VMO,或是攔截 zx_handle_close
。不過,這項做法無法實現位址空間複製功能,因為載入器服務會在程序開始執行前將部分 VMOs 對應至該程序,這無法協助您取得這些程序的句柄。我們可以修改載入器服務,將必要的句柄傳遞至程序,但這比新增此系統呼叫更費工。
既有技術與參考資料
https://chromium.googlesource.com/chromium/src/+/master/docs/linux/zygote.md http://neugierig.org/software/chromium/notes/2011/08/zygote.html