RFC-0002:Fuchsia 平台版本管理

RFC-0002:Fushisia 平台版本管理
狀態已接受
領域
  • 一般
說明

使用版本管理功能讓平台持續進化,同時提供相容性。

更小鳥
作者
審查人員
提交日期 (年月分)2020-04-30
審查日期 (年-月-日)2020-05-23

摘要

本文提議針對 Fuchsia 平台提出「API 級別」和「ABI 修訂版本」的概念。開發人員會根據「目標 API 級別」進行建構,而這個級別會決定應用程式可以看見哪些宣告。目標 API 級別也會嵌入在已編譯的應用程式中,作為「目標 ABI 修訂版本」,這表示應用程式預期的語意。指定的 Fuchsia 平台版本通常會支援多個 ABI 修訂版本,讓平台執行較舊的應用程式,同時提供改進平台的路徑。

提振精神

目前 Fuchsia 平台透過一系列的軟性轉換演進。如要變更 Fuchsia 系統介面的一部分,平台會先導入新版介面。之後,應用程式就會遷移至新版介面。在所有應用程式都遷移至新版介面後,平台會移除舊介面。

使用這種方法時,平台的演進速度只能像最慢的應用程式一樣快。平台必須等待最後一個應用程式遷移舊介面,才能完成軟性轉換作業。隨著應用程式數量增加,平台與應用程式之間的耦合量減少,軟性轉換需要更長的執行時間。最終,我們無法透過軟性轉場效果改進平台。

這項 RFC 有助於解決下列問題:

Fuchsia 平台如何持續發展,並且能夠長時間執行更多較舊的應用程式?

為何現在發行?

我們有些客戶希望平台能提高穩定性。如果我們現在提供穩定性資訊,就會放慢改善平台的能力。為了滿足這些目前的客戶需求,平台必須能夠提供較長的相容性視窗,且不會使專案停滯。

此外,Windows 的好處是,我們可以先在應用程式中嵌入目標 ABI 修訂版本,再長時間與這些應用程式提供二進位檔相容性。Windows 錯失了這個機會,現在會嘗試用經驗法則猜測二進位檔的目標 ABI 修訂版本,這會造成開發人員的痛苦。

術語

Fuchsia 的版本是 Fuchsia 作業系統的建構版本,以及相關套件,已部署至使用者族群。版本會有版本號碼,可以識別該版本包含的一組軟體構件。

回溯相容性是指較新版本的 Fuchsia 執行預定在舊版 Fuchsia 上執行的二進位檔。

Fuchsia IDK 是開發環境整合商會使用成果,向開發人員公開 Fuchsia 平台,以建構在 Fuchsia 上執行的應用程式。Fuchsia IDK 是由 Fuchsia 專案發布,並定義 Fuchsia 平台與在 Fuchsia 上執行的應用程式之間的合約。 IDK 工具定義 Fuchsia IDK 工具與開發環境整合商環境之間的合約。

「軟性轉換」是一種技術,可將回溯不相容的變更細分為一系列較小的平台變更,以及一組已知二進位檔,以便在每個步驟本機維持相容性。

設計

本文件所述的設計是對 Fuchsia 系統介面版本,讓平台和應用程式同意應用程式預期的語意。

具體來說,如果應用程式可在指定的 Fuchsia 版本上運作,除非 Fuchsia 刻意終止應用程式支援,否則該應用程式應繼續在未來的 Fuchsia 版本中運作。這項設計並未解決在 Fuchsia 舊版中建立新的應用程式的相關問題。

版本管理

Fuchsia 平台使用兩種版本 ID:「API 級別」和「ABI 修訂版本」。這兩個版本都會識別平台提供的「介面」,而非該介面的「實作」。Fuchsia 的版本採用不同的版本管理配置,可識別該版本的特定實作。

指定 API 級別會導致特定的 ABI 修訂版本,但多個 API 級別可能暗示同一個 ABI 修訂版本。

API 級別

Fuchsia「API 級別」表示建構應用程式時可用的一組 API。Fuchsia IDK 的某個版本通常支援多個 API 級別。指定支援 API 級別提供的 API 必須在不同的 IDK 版本中保持一致。

範例:考慮使用 pkg/fit,這是 SDK 中的 C++ 程式庫。fit 程式庫會宣告多個函式,每個函式都是程式庫公開的 API。API 定義了一組函式,這意味著兩個 IDK 版本應在相同 API 級別的 fit 程式庫中公開同一組函式。

就語法而言,Fussia 的「API 級別」是未帶正負號的 64 位元整數。隨著平台演進 (請見下方演進),API 級別會以遞增順序指派,讓人類 (包括開發人員) 能夠理解。

ABI 修訂版本

Fuchsia ABI 修訂版本表示應用程式預期平台提供的 Fuchsia 系統介面語意。特定版本的 Fuchsia 通常支援多個 ABI 修訂版本,但特定支援的 ABI 修訂版本的語意應在 Fuchsia 版本中保持一致 (請參閱下方「演化」一節)。

範例:請考慮使用 zx_clock_get_monotonic,這是 vDSO 在 Fuchsia 系統介面中公開的函式。ABI 修訂版本會指定這個函式是否存在,以及呼叫這個函式時會發生的情況,也就是在同一個 ABI 修訂版本中,zx_clock_get_monotonic 的語意應一致。

Fuchsia 的「ABI 修訂版本」是合成的 64 位元整數。ABI 修訂版本是沒有內部結構的不透明 ID,如要為新的 ABI 修訂版本建立 ID,請隨機選取從未用來識別 Fuchsia ABI 修訂版本的未簽署 64 位元整數。

系統會隨機選擇 ABI 修訂版本 ID,避免開發人員猜測未來的 ABI 修訂版本 ID,並且對日後的「Fuchsia 系統介面」語意設下期望。因此,ABI 修訂版本僅供機器理解,而且很少人能解讀。

演進

每當平台在 Fuchsia IDK 中新增或移除 API,或 ABI 修訂版本變更時,平台就會增加 API 級別。實際上,專案可能會以某些定義的頻率 (例如每天或每週一次) 提高 API 級別,來批次變更。

每當平台對 Fuchsia 系統介面的語意做出回溯不相容的變更時,平台會變更 ABI 修訂版本。實際上,專案可能會透過某些既定的頻率 (例如每六週或每六個月) 變更 ABI 修訂版本,藉此批次執行回溯不相容的變更。

在此限制中,語意的每個變更可能回溯不相容,但實際上作業系統可能會在不破壞應用程式的情況下對其語意進行變更。舉例來說,許多常見的作業系統都會新增系統呼叫,而不會破壞應用程式。

待辦事項:建立文件,詳述 Fuchsia 系統介面的變更,使其具有回溯相容性。專案可能需要經過一段時間的修正,因為專案可以瞭解常會變更哪些變更,而且不會破壞應用程式的實際操作。

應用程式

開發人員在建構元件時,會選取單一「目標 API 級別」。建構元件時,目標 API 級別可以控管 Fuchsia IDK 中可以使用哪些宣告。舉例來說,建構指定 API 級別 6 的元件時,無法使用 API 級別 7 中導入的 FIDL 訊息,但建構指定 API 級別 7 或 8 的元件時可使用 (假設訊息在 API 級別 8 中未淘汰)。

建構元件時,SDK 中的工具會在元件的資訊清單中加入與目標 API 級別相關聯的目標 ABI 修訂版本。這樣一來,每個元件都會宣告平台在建構元件時預期提供的語意。特定套件可包含許多元件,每個元件都可以選取其偏好的目標 ABI 修訂版本。

平台

平台維護了支援的 ABI 修訂版本清單。平台為針對支援 ABI 修訂版本的元件提供二進位檔相容性,這表示平台會嘗試為目標 ABI 修訂版本指定的平台語意提供這些元件。

範例:請考慮從 fuchsia.foo.Bar 通訊協定轉換到 fuchsia.foo.Bar2 通訊協定。假設元件 baz.cm 有目標 ABI 修訂版本,指出元件預期平台會提供 fuchsia.foo.Bar。執行 baz.cm 時,平台會將 fuchsia.foo.Bar 的要求轉送至適當的實作。不過,在轉換至 fuchsia.foo.Bar2 後,執行具有目標 ABI 修訂版本的元件時,平台不會再將 fuchsia.foo.Bar 的要求轉送至實作項目,因為指定 ABI 修訂版本的元件應改用 fuchsia.foo.Bar2

平台有時可能會希望移除對指定 ABI 修訂版本的支援。這類移除作業通常取決於仍仰賴舊版 ABI 修訂版本的重要元件。平台不會維護舊版 ABI 修訂版本隱含的完整語意,而是會維護一份「舊版元件」清單以及執行這些特定元件所需的「相容」表格。「相容」輔助鍵可讓舊版元件使用其他不支援的介面。使用這項機制時,平台可以移除對舊版 ABI 修訂版本的一般支援,同時仍然可以執行以舊版 ABI 修訂版本為目標的重要元件。

範例:假設平台不再支援包含 fuchsia.foo.Bar 的任何 ABI 修訂版本,但 baz.cm 是尚未遷移至 fuchsia.foo.Bar2 的重要元件,專案可以將 baz.cm 視為具有 needs-fuchsia-foo-bar 對等的舊版元件。即使平台不支援 baz.cm 的目標 ABI 修訂版本,平台仍可繼續執行 baz.cm,方法是將對 fuchsia.foo.Bar 的要求轉送至相容性輔助程式 (可能使用 fuchsia.foo.Bar2 實作)。相容性輔助程式不需要支援 fuchsia.foo.Bar 隱含的完整語意。相反地,相容性輔助程式只需要正常運作,可讓 baz.cm (以及具有 needs-fuchsia-foo-bar 相容的其他特定元件) 正常運作。

平台無法執行未指定支援的 ABI 修訂版本或列為舊版元件的元件,因為平台不知道這些元件預期的語意。

生命週期

Fuchsia 系統介面的每個元素 (例如系統呼叫或 FIDL 訊息) 都會經歷下列生命週期:

  1. 系統會將元素導入到平台中。開發人員必須先在 Fuchsia 發布包含該元素的新 API 級別時,才能使用這個 API。如果元素可在不破壞 ABI 的情況下導入 (例如新增系統呼叫),則可更新現有 ABI 修訂版本的語意,以納入新導入的元素。否則,必須隱藏指定舊版 ABI 修訂版本的元件,以免破壞這些元素。
  2. 如果可以,您可以加入子元素來extended元素。舉例來說,您可以導入新的欄位來擴充 FIDL 資料表。推出子元素後,會啟動該子項元素元素生命週期的另一個例項,包括要求新的 API 級別才能讓開發人員看到該元素的 API。只有在新增子項元素不會破壞現有的 API 或 ABI 時,才能擴充元素。
  3. 元素可能已淘汰。如果元件指定舊版 ABI 修訂版本,則在較新的平台版本中執行時,仍可使用該元素。然而,指定較新 API 級別的開發人員將無法再使用該元素。
  4. 當平台不再支援元素的「簡介」和「淘汰」之間的 ABI 修訂版本時,該元素即為「舊版」。此時,平台只需要支援元素基本,因為該元素實際上是由特定的舊版元件透過同等的舊版元件使用。
  5. 當所有舊版元件都未使用該元素時,您就可以從平台上完全移除該元素。

動力學

這個方法會結合存取新 API 來執行這類遷移作業,藉此鼓勵開發人員停用已淘汰的介面。具體來說,如要取得新推出 API 的存取權,開發人員必須變更目標 API 級別,例如要求他們停用已在該 API 級別中淘汰的任何介面。

實作

這項設計牽涉到 Fuchsia 系統的許多層。本文件概略說明每個植入層所需的變更,但這些層的詳細設計留待後續文件中。

FIDL

FIDL 應提供一種方法,針對每個通訊協定元素可用的 API 級別加上註解。FIDL 工具鍊應瞭解目標 API 級別,並產生該 API 級別適用的程式碼。

如果通訊協定元素 (例如表格中的欄位或通訊協定中的訊息) 在特定 API 級別淘汰,在理想情況下,指定該 API 級別的元件就能接收包含該通訊協定元素的訊息,但想要防止這些元件傳送包含該通訊協定元素的訊息。

系統標頭

系統標頭應讓開發人員指定目標 API 級別,然後根據目標 API 級別,使用這些標頭調整可見的 API 組合。此外,系統標頭也應定義巨集,以便將其他程式庫中的宣告瀏覽權限限制在特定 API 級別。

vDSO

系統應提供多個 vDSO,每個 vDSO 都支援 ABI 修訂版本清單。系統應該盡可能透過回溯相容的方式擴充 vDSO,但如果沒有可行,系統便可利用個別支援的 ABI 修訂版本清單來建立新的 vDSO。

擴充 vDSO 會增加現有二進位檔的攻擊面,因為這些現有的二進位檔可以存取 vDSO 擴充功能。在決定是否要擴充現有的 vDSO 或是否要挖掘新的 vDSO 時,該專案應考量安全性影響以及相容性的影響。

vDSO 可提供函式,檢查 vDSO 是否支援指定的 ABI 修訂版本,但 vDSO 不應直接公開支援的 ABI 修訂版本清單,因為對應用程式公開清單會導致應用程式在擴充清單後中斷。

程序架構

啟動程序時,用戶端應告知程序啟動器,ABI 預期會修訂該程序。程序啟動器應使用該資訊選取適當的 vDSO,並為新啟動的程序處理啟動訊息。

開放式問題。在建立沒有元件資訊清單的程序時,我們應該使用什麼 ABI 修訂版本?其中一種可能性是將 ABI 修訂版本放在可執行檔的 ELF 資料中,而不是放在元件資訊清單中。另一種方式是將 ABI 修訂版本新增至 fuchsia.ldsvc.Loader 通訊協定,而系統通常會轉送至執行檔的來源。

元件架構

建構元件資訊清單的工具應將目標 API 級別視為指令列參數,並在其建立的元件資訊清單中嵌入對應的 ABI 修訂版本。

雖然不需要立即使用,但元件最終仍會希望根據 ABI 修訂版本調整能力路徑。例如,元件可能希望停止向其中一個子項元件提供特定服務。如果立即移除服務,可能會中斷與該子項元件的舊版相容性。父項可能可能只想為指定較舊的 ABI 修訂版本的子項提供服務。

同樣地,平台也可能會想將特定舊版元件的功能轉送至提供相容性提示的特殊目的地。例如,我們可以定義轉送「特殊」路徑,套用到相容資料表中具有同樣程度的特定舊版元件。

SDK

SDK 應以機器可讀取的格式 (例如 JSON 中繼資料) 指定 SDK 支援的 API 級別,以及這些 API 級別與 ABI 修訂版本之間的對應關係。您應修改 SDK 整合,以便讓開發人員指定目標 API 級別,並將目標 API 級別做為指令列引數提供給所有需要該值的工具。

效能

本提案會在建構和探索過程中介入主要版本,嘗試以盡量降低平台版本管理的效能影響。用於執行舊版元件的相容性限制可能會對效能產生重大影響,但專案在將元件新增至舊版元件清單時,可以根據個案評估這些效能影響。

安全性考量

本提案應該對安全性有正面影響,因為本提案可讓您更輕鬆地將 Fuchsia 軟體生態系統遷移至較新的 API,因為該 API 的安全性屬性也許比舊版 API 更佳。

此外,配置新的 ABI 修訂版本還能避免將新的 ABI 提供給現有應用程式,這可以減少應用程式暴露在攻擊中的途徑。在決定是否要擴充現有的 ABI,或是是否要分配新的 ABI 修訂版本時,專案應考量分配新的 ABI 修訂版本的安全性優勢。

本提案提供了一種機制,讓惡意應用程式能夠選取平台上其他可能較舊的程式碼路徑,例如藉由聲稱指定較舊的 ABI 修訂版本。隨著平台不斷演進,專案必須處理支援舊版 ABI 修訂版本的程式碼,並採用與專案處理支援較新 ABI 修訂版本的程式碼相同的安全防護措施。

隱私權注意事項

本提案應該對隱私權有正面影響,因為本提案可以更輕鬆地將 Fuchsia 軟體生態系統遷移至較新的 API,而 API 的隱私權屬性應比舊版 API 更佳。

測試

本提案會稍微增加測試矩陣,因為平台的行為會因執行中元件的 ABI 修訂版本而異。我們需要將測試矩陣中的增加情形,計入 Fuchsia Compatibility Test Suite (CTS) 的設計。例如,專案可能想要根據 ABI 修訂版本建立 CTS 版本,確保平台不會在不斷演化時對舊版 ABI 修訂版本提供迴歸支援。

說明文件

您應更新平台的說明文件,以針對各個 API 在生命週期中的目前階段及其生命週期記錄 (例如 API 推出、淘汰和/或移除時間) 加上註解。這些註解應取自相同資料來源,用於控制應用程式在目標特定 API 級別時是否能存取這些 API。舉例來說,fidldoc 工具應該瞭解 FIDL 來源檔案中的 API 級別註解,並在產生的說明文件中產生適當的註解。

每當平台建立新的 ABI 修訂版本 ID,專案應更新說明文件,說明新的 ABI 修訂版本無法回溯相容的方式,以及更新應用程式時應採取的行動 (如有)。

此外,專案應該包含一些概念說明文件,解釋平台為何採用 API 級別,以及如何從 API 級別升級至另一個 API 級別。

缺點、替代與不明

採行此提案需要多少費用?

導入本提案的主要成本,會隨著平台的進化而增加。新增 API 現在需要跨專案協調,才能在新的 API 級別中發布該 API。同樣地,淘汰 ABI 也變得更加複雜,因為淘汰作業會在多個步驟中進行。

系統本身也變得更加複雜,因為系統的行為將部分取決於每個元件的 ABI 修訂版本。

還有哪些策略或許能解決相同的問題?

另一個平台採用的另一個策略是永不移除功能。比如,網路平台發展幾乎完全相輔相成。 在某些方面,這種方式會比較簡單,因為系統不需要特定機制來淘汰功能。

另一個做法是針對系統的不同部分使用不同的版本 ID,而不是套用至整個系統的單一 API 級別。在某種程度上,Fuschsia 也採用這種做法。舉例來說,每個檔案系統都有自己的版本 ID,用於在磁碟上表示法和檔案系統的記憶體內程式碼之間簽訂合約。整個系統使用單一 API 級別意味著對平台與應用程式之間的合約演變程度進行一定程度的協調。

既有藝術與參考資料

這個主題之前有許多相關的藝術品。本文中的提案是以 Android、Windows 和 macOS/iOS 的體驗為基礎。

Android

Android 提供了 API 級別的概念。每個 Android 平台介面都會加上導入介面的 API 級別。Android 應用程式也會使用 uses-sdk 元素,在資訊清單中指定目標 API 級別。原則上,Android 可以利用這種 API 級別機制來淘汰及移除舊有介面。

Windows

Windows 會大量使用與 ABI 修訂版本類似的概念,後者會顯示為應用程式資訊清單中的 SupportedOS 項目。Windows 使用 GUID 來識別應用程式指定的 ABI 修訂版本,這類似於本文件中的提案,使用不透明的 64 位元整數。

在 Windows 中,SupportedOS GUID 會與特定 Windows 版本相關聯。例如,e2011457-1546-43c5-a5fe-008deee3d3f0 可識別 Windows Vista。不過,新版 Windows (例如Windows 7) 瞭解 e2011457-1546-43c5-a5fe-008deee3d3f0 GUID,並提供與 Windows Vista ABI 的相容性。本文件提案將 ABI 修訂版本與更靈活的平台版本分離。

macOS、iOS

macOS 和 iOS 均使用 API_AVAILABLE@available 註解,控制建構應用程式時是否可使用宣告。系統程式庫 (又稱架構) 也會使用「Linked on or after」檢查和明確的相容資料表,以支援需要來自平台舊版語意的舊版應用程式。

Apple 已運用這些機制,成功將這些作業系統的應用程式從舊版 API 遷移至新版 API。