| RFC-0013:複製 VMO 對應 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 系統呼叫,可從對應項目建立 VMO 的 CoW 副本,不需要控點。 |
| 問題 | |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2020-10-26 |
| 審查日期 (年-月-日) | 2020-12-09 |
摘要
目前只有在擁有 VMO 控制代碼的情況下,才能建立 VMO 的 CoW 副本。這不足以用於 Zygote 使用情境,因為這類情境需要 CoW 複製整個位址空間,包括所有 VMO 控制代碼已關閉的對應。這項 RFC 提議採用新的系統呼叫,以解決這個缺口。
動機和問題陳述
Linux 上的 Chromium 會從 Zygote 程序分叉,藉此產生算繪器,大幅節省記憶體和 CPU 資源。我們希望在 Fuchsia 上實現這些節省。
為此,我們需要實作「位址空間複製」作業,
- 程序根 VMAR
- 某些控點會參照位址空間中對應的 VMO
以上指令會傳回:
- 新程序,其位址空間會填入輸入程序中對應 VMO 的副本
- 對於輸入程序中參照 VMO 的每個控制代碼,新程序中參照該 VMO 對應複製項的新控制代碼
加入這個系統呼叫後,我們就能在使用者空間中輕鬆實作這項功能。這項作業的原理是使用 ZX_INFO_PROCESS_MAPS 取得位址空間配置,並使用 zx_vmar_create_vmo_child 建立每個對應的副本,但有控制代碼的 VMO 除外,這些 VMO 會使用 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)
Creates a CoW clone of the pages mapped in the range addr to addr+size
in the VMAR referenced by handle.
範圍必須是單一 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_vmo_create_child,藉此實作 zx_vmar_create_vmo_child 的使用者空間。但一般來說,Zircon API 只允許鑄造新建立物件的控制代碼,以便更容易分析介面。這個系統呼叫必須憑空建立控制代碼。
有許多技巧可用於避免關閉任何 VMO 控制代碼,例如修改所有建立及對應 VMO 的程式碼,避免關閉這些控制代碼,或是攔截 zx_handle_close。不過,這不足以實作位址空間複製,因為載入器服務會在程序開始執行前,將部分 VMO 對應至程序,而這無法協助您取得這些 VMO 的控制代碼。我們可以修改載入器服務,將必要的控制代碼傳遞至程序,但這比新增這個系統呼叫更費工。
既有技術和參考資料
https://chromium.googlesource.com/chromium/src/+/master/docs/linux/zygote.md http://neugierig.org/software/chromium/notes/2011/08/zygote.html