| RFC-0236:VMO 快照修改的副本 | |
|---|---|
| 狀態 | 已接受 |
| 區域 |
|
| 說明 | 目標是導入新的 VMO 子類型,讓您擷取快照,捕捉分頁支援 VMO 中所有已修改的頁面。 |
| 問題 | |
| Gerrit 變更 | |
| 作者 | |
| 審查人員 | |
| 提交日期 (年-月-日) | 2023-07-20 |
| 審查日期 (年-月-日) | 2023-12-12 |
摘要
目標是導入新的 VMO 子項類型,讓您能夠擷取以分頁器為基礎的 VMO 子項中,任何經過修改的頁面快照。
提振精神
核心目前支援兩種類型的 VMO 複製 (也稱為子項 VMO):真正的快照 (複製作業完成後,兩個 VMO 都不會看到彼此的變更),以及至少在寫入時建立快照的複製 (作業完成後,子項可以看到父項 VMO 的變更,但子項寫入的頁面除外)。
您可以在 VMO 副本上重複執行複製作業,建立子 VMO 的階層。為方便實作,Zircon 核心不允許混合式階層;您可以建立真正的快照階層,也可以建立寫入時快照 VMO 的階層。
隨著 Starnix 的發明,Fuchsia 必須有效支援 fork()。 Fork 會將父項程序的整個位址空間複製到子項程序,包括匿名記憶體,以及分頁支援的資料和程式碼 VMO。
問題在於核心只支援匿名記憶體的真正快照,而對於分頁支援的 VMO,核心只支援寫入時複製的快照。因此,無法透過複製滿足 fork() 合約,Starnix 必須強制實作急切複製和/或其他 CPU 與記憶體密集型解決方法。
利害關係人
誰會受到這項 RFC 是否通過的影響?(這個部分為選填,但建議填寫)。
csuter@google.com、jamesr@google.com
協助人員:
davemoore@google.com
審查者:
rashaeqbal@google.com、jamesr@google.com
已諮詢:
列出應審查 RFC 的人員,但不必取得他們的核准。
csuter@google.com、adanis@google.com、cpu@google.com、mvanotti@google.com、 lindkvist@google.com
社交:
設計文件已與 Zircon 團隊和 starnix 的部分成員分享,並與利害關係人分享正在進行的 CL,以供基準測試。
需求條件
- 有效支援複製同時具有分頁備份 VMO 和匿名 VMO 的位址空間。
- 如果程序無法存取 VMO (最後一個控制代碼已關閉),父項 VMO 或子項 VMO 都不應浪費記憶體。換句話說,這兩種情況都不應浪費記憶體:
vmo = create_vmo();
loop {
child = create_snapshot_modified(vmo)
child.write(...)
vmo = child // old vmo is dropped
}
vmo = create_vmo();
loop {
vmo.write(...)
child = create_snapshot_modified(vmo)
// child is dropped
}
設計
ZX_VMO_CHILD_SNAPSHOT_MODIFIED 是新型 VMO 複製項,可建立經過快照修改的子類型。
這個旗標會建立子項,保留由分頁器支援的 VMO 子項修改的任何頁面快照。就語意而言,這就像是對父項中任何未由分頁器支援的頁面執行急切複製。父項中由分頁器支援的頁面,至少會以寫入時複製語意複製到副本中。這與原始快照語意不同,原始快照語意會像是在 VMO 的所有頁面上建立急切副本。
首次在分頁支援的 VMO 上使用時,語意行為會如同使用 SNAPSHOT_AT_LEAST_ON_WRITE。系統會建立複製項的控制代碼,該控制代碼一開始與父項相同,但修改複製項會導致兩者不同。
如果對任何匿名 VMO 使用 SNAPSHOT_MODIFIED,複製作業會升級為具有快照語意,類似於 SNAPSHOT_AT_LEAST_ON_WRITE 使用的現有複製類型升級語意。
這個標記不適用於複製具有釘選區域、切片或衍生自 zx_vmo_create_physical() 或 zx_vmo_create_contiguous() 的 VMO。
保護殼
在分頁支援的 VMO 上修改快照
建立單一 SNAPSHOT_MODIFIED 分頁支援 VMO 的副本時,行為會如同建立單一 SNAPSHOT_AT_LEAST_ON_WRITE 副本。複製時,新的 VMO 會與父項完全相同。
在對副本執行另一個 SNAPSHOT_MODIFIED 之前,副本仍可修改。複製作業中未修改的頁面至少會具有寫入時複製語意。
快照修改時間晚於至少一次寫入或快照修改時間
的頁面支援 VMO
由於 SNAPSHOT_MODIFIED 和 SNAPSHOT_AT_LEAST_ON_WRITE 在分頁支援的 VMO 上行為相同,因此在分頁支援的複製項目上呼叫 SNAPSHOT_MODIFIED 時,兩種情況都會產生相同的語意。任何不再由分頁支援的頁面都會有快照,而由分頁支援的頁面至少會有寫入時複製語意。
快照修改日期晚於快照
在這種情況下,語意會升級為快照,類似於 snapshot-at-least-on-write。
不支援的案件
目前不支援下列情況,如果嘗試複製 SNAPSHOT_MODIFIED,系統會傳回 ZX_ERR_NOT_SUPPORTED。
快照修改的快照結尾 (至少在寫入鏈結上)
快照修改項可能會擴充,用於快照鏈結的結尾 (至少在寫入時)。不過,這可能會導致結果混淆,因為來自複製 VMO 的未分叉頁面可以查看單向 VMO 鏈中的所有修改內容,而最接近的親屬就是讀取的內容。這與原始承諾不一致,因為原始承諾指出可以建立任何修改過頁面的快照。
在至少一個寫入鏈結的快照中途修改快照
如果 VMO 有子項 (也就是位於快照至少寫入一次的鏈結中),就絕不能使用快照修改功能,因為這可能會導致階層不一致。
命名法
zx_vmo_create_child() 中複製類型旗標的現有命名慣例,旨在以描述所提供語意的方式命名旗標。這個旗標目前的名稱是 SNAPSHOT_MODIFIED,因為它會摘要說明複製版本中修改過的頁面會建立快照的行為。類似的選項是 SNAPSHOT_MODIFICATIONS。其他考慮的旗標包括 SNAPSHOT_MIXED,這個旗標確實描述了語意,但較不清楚;SNAPSHOT_PAGER_MODIFICATIONS 也是考慮的旗標,但將 VMO 與分頁器配對並不理想。
實作
快照修改作業會影響 Zircon 中的許多檔案,但可以分成 CL,在將選項標記新增至系統呼叫之前,先在核心內部新增對新快照類型的支援。
我們會加入一些核心內測試,在第一階段驗證新結構的正確行為,並在導入選項標記時,加入更複雜的核心測試。
效能
在大多數情況下,系統只會在建立新的快照修改複製項目時呼叫新加入的程式碼,因此現有程式碼的效能不會有非預期的變化。唯一的例外是建立子項時,簡單的方法會額外取得 VMO 鎖定,但如果這會導致效能降低,重新建構複製選取程式碼來避免這種情況,將會是微不足道的事。SNAPSHOT_AT_LEAST_ON_WRITE
安全性考量
Snapshot-modified 是使用現有的 Zircon 基本類型建構而成,且未導入任何新功能,因此不太可能造成任何安全漏洞。
測試
核心單元測試和核心測試會隨附於相關 CL。
說明文件
我們將發布詳細的設計文件,供 Zircon 開發人員參考。內容包括新資料結構、支援和不支援的案例、程式碼變更、挑戰和替代方案。
系統會在 zx_vmo_create_child() 中新增旗標,並提供以下說明:
ZX_VMO_CHILD_SNAPSHOT_MODIFIED - 建立子項,其行為就像是在父項中任何未由分頁器支援的頁面上執行急切複製作業,也就是由分頁器支援的 VMO 子項修改的頁面。以分頁器為後端的頁面至少會具備寫入時複製語意。這個標記可能無法用於以 zx_vmo_create_physical()、zx_vmo_create_contiguous() 建立的 VMO、含有釘選頁面的 VMO,或這類 VMO 的子項。如果使用 SNAPSHOT_AT_LEAST_ON_WRITE 建立的任何 VMO 具有非切片子項,或不是以分頁支援的 VMO 子項,也不支援這個標記。
缺點、替代方案和未知事項
使用現有的 Zircon VMO 基本類型,為分頁器支援的 VMO 建立快照語意並不容易。使用者分頁器會處理單一 VMO 的頁面要求,目前其子項會形成單一單向鏈結,並採用寫入時複製語意。
可在匿名 VMO 上使用的快照旗標會建立隱藏的 VmCowPages,這是目標 VMO 和新快照的共同祖先。由於沒有任何項目指向隱藏的 VmCowPages,因此無法修改其頁面,屬於不可變動。這個隱藏的 VmCowPages 會保留目標 VMO 中的頁面,子項的修改內容具有寫入時複製語意。因此,搜尋這個階層中的網頁時,系統會向上走訪樹狀結構,並在隱藏的根節點結束。
由於根 VMO 一律會隱藏,而原始 VMO 會成為左側子項,因此很難使用現有的快照資料結構供分頁器使用。如果分頁器仍指向原始 VMO (現在有隱藏的上層),分頁器作業就必須向上傳播至隱藏的根,才能在子項要求時提供頁面。這樣會造成不一致,因為頁面會新增至未運作的節點。
最簡單的解決方案是建立混合階層,其中根層級是可見的,且具有單一隱藏子項,可做為快照樹狀結構的隱藏根層級。
向使用者說明提供的語意有多種方式。RFC 中的說明會針對分頁程式提供行為,但另一種做法是只修改及複製網頁。舉例來說:
「這個標記會建立子項,保留父項中任何已修改頁面的快照。如果根 VMO 在快照發生後寫入未修改的頁面,快照修改的子項就會看到變更。這與原始快照語意不同,原始快照語意會像建立急切副本一樣運作。
這項說明正確無誤,但需要進一步釐清附帶條件,也就是這項行為需要呼叫器,因為在匿名 VMO 上使用時,這個旗標會升級為快照語意。
SNAPSHOT_MODIFIED 可以取代 SNAPSHOT_AT_LEAST_ON_WRITE 嗎?
淘汰「至少在寫入時建立快照」並以「快照已修改」取而代之並非易事,因為這兩種副本的語意不同,可能會導致非預期的行為。雖然這兩種複製類型都提供「至少寫入時複製」語意,但 snapshot-modified 可以在同一個 VMO 中混合使用快照和「至少寫入時複製」頁面。此外,這項變更還需要進行效能測試。當 VMO 受到分頁支援時,由於不會建立隱藏的常見祖先,因此每次建立副本時,快照至少會分配寫入的記憶體較少。因此,如果將所有 snapshot-at-least-on-write 用途遷移至 snapshot-at-least-on-read,可能會在某些用途中造成效能回歸。
不過,由於大多數 fdio 輔助程式都會提供與 SNAPSHOT_MODIFIED 相容的語意,因此可能值得研究是否要替換 SNAPSHOT_AT_LEAST_ON_WRITE,簡化 zx_vmo_create_child() 的 API。