虛擬 A/B 版本總覽

Android 有兩種更新機制:A/B (自動) 更新和非 A/B 更新。 為降低程式碼複雜度並強化更新程序,在 Android 11 中, 透過虛擬 A/B 統整兩種機制 大幅降低儲存空間成本Android 12 提供了虛擬 A/B 壓縮選項,可用於壓縮快照分區。 在 Android 11 和 Android 12 中,請注意下列事項 套用:

  • 虛擬 A/B 更新流暢,例如 A/B 更新。虛擬 A/B 更新 盡可能縮短裝置離線且無法使用的時間。
  • 虛擬 A/B 更新可以復原。如果新的作業系統無法啟動 就會自動復原至先前的版本
  • 虛擬 A/B 更新只會使用複製的 系統啟動載入程式使用的分區。其他可更新的分區 建立快照
,瞭解如何調查及移除這項存取權。

背景與術語

本節定義術語,並介紹 虛擬 A/B 版本

裝置對應工具

裝置對應程式是在 Android 中經常使用的 Linux 虛擬區塊層。取代為 動態分區,例如 /system 是多層裝置的堆疊:

  • 堆疊的底部是實體「超級」分區 (例如, /dev/block/by-name/super)。
  • 中間是 dm-linear 裝置,用於指定疊加畫面中的哪個區塊 分區即為特定分區這會顯示為 A/B 裝置上的 /dev/block/mapper/system_[a|b],或 /dev/block/mapper/system
  • 頂部位於針對已驗證的分區建立的 dm-verity 裝置。 這部裝置會驗證 dm-linear 裝置上的區塊是否經過簽署 正確。這會顯示為 /dev/block/mapper/system-verity,而且是來源 /system 掛接點的邊緣。

圖 1 顯示 /system 掛接點下方的堆疊外觀。

底下的分區堆疊
系統

圖 1. /system 掛接點下的堆疊

dm-snapshot

虛擬 A/B 仰賴 dm-snapshot,這是一種裝置對應程式模組,可用來建立 保持在儲存狀態使用「dm-snapshot」時,共有四部裝置 播放:

  • 「base」裝置是指要建立快照的裝置。在這個頁面上 裝置一律為動態分區,例如系統或廠商。
  • 寫入複製 (COW) 裝置,用於記錄基礎裝置的變更。這項服務 可以是任何大小,但必須夠大才能配合 基本裝置。
  • 快照裝置是以 snapshot 目標建立。寫入 快照裝置會寫入 COW 裝置。從快照讀取 裝置讀取時,系統會視情況從基礎裝置或 COW 裝置讀取資料 是否遭到快照變更要存取的資料。
  • origin 裝置是以 snapshot-origin 目標建立。讀取目標 直接從基礎裝置讀取來源裝置。寫入來源 裝置會直接寫入基礎裝置,但原始資料會備份 寫入 COW 裝置

裝置對應:
dm-snapshot

圖 2. dm-snapshot 的裝置對應

壓縮快照

在 Android 12 以上版本中,因為 /data 分區可能偏高,您可以在 以解決 /data 分區中較高的空間需求。

虛擬 A/B 壓縮快照是以下列元件為基礎建構而成 支援 Android 12 以上版本:

  • dm-user,這個核心模組與 FUSE 類似,可提供使用者空間 實作區塊裝置
  • snapuserd,這是用於實作新快照的使用者空間 Daemon 格式。

這些元件會啟用壓縮。對 會實作壓縮快照功能,詳情請參閱下一節: 壓縮快照的 COW 格式dm-userSnapuserd

壓縮快照的 COW 格式

在 Android 12 以上版本中,壓縮快照會使用 COW 格式。與用於未壓縮的核心內建格式相似 快照,壓縮快照的 COW 格式會有交替的區段 中繼資料和資料原始格式的中繼資料只能替換 作業:將基本映像檔中的區塊「X」替換為區塊 Y 的內容 快照壓縮後的快照 COW 格式更能淺顯易懂 支援下列作業:

  • 複製:在基準裝置中,應使用區塊 Y 取代基準裝置中的「X」 存取。
  • 取代:應將基本裝置中的「X」替換為內容 區塊 Y每個區塊都會經過 gz 壓縮。
  • 0:必須將基本裝置中的區塊「X」替換成所有 0。
  • XOR:COW 裝置會在區塊 X 與 區塊 Y。(適用於 Android 13 以上版本)。

完整的 OTA 更新僅包含「取代」和「零」作業。成效增幅 OTA 更新可能會另外執行複製作業。

Android 12 中的 dm-user

dm-user 核心模組可讓 userspace 實作裝置對應工具區塊 裝置。dm-user 資料表項目會在 /dev/dm-user/<control-name>userspace 程序可將裝置輪詢 接收來自核心的讀取和寫入要求。每個要求都有相關聯的 緩衝區,供使用者填入 (用於讀取) 或傳播 (針對寫入)。

dm-user 核心模組為核心提供新的使用者可見介面 不屬於上游 kernel.org 程式碼集的一部分在此之前,Google 保留在 Android 中修改 dm-user 介面的權利。

Snapuserd

dm-usersnapuserd 使用者空間元件實作虛擬 A/B 。

在未壓縮版本的虛擬 A/B 中 (Android 11 以下版本,或 中,沒有壓縮快照選項。 COW 裝置為原始檔案啟用壓縮後,COW 函式 而是 dm-user 裝置,這樣會連線至 snapuserd Daemon。

核心不會使用新的 COW 格式。snapuserd 元件 會在 Android COW 格式與核心內建元件之間轉譯要求 格式:

Snapuserd 元件在 Android COW 格式與核心之間轉譯要求
內建
格式

圖 3. 貼齊使用者成為 Android 與核心之間的翻譯流程圖 COW 格式

磁碟一律不會進行這項轉譯和解壓縮作業。snapuserd 元件攔截在核心中發生的 COW 讀取和寫入; 以 Android COW 格式實作。

XOR 壓縮

如果裝置搭載 Android 13 以上版本, XOR 壓縮功能預設為啟用,可啟用使用者空間 快照,可在舊區塊和新區塊之間儲存 XOR 壓縮的位元組。時間 在虛擬 A/B 更新中,區塊中只有少數位元組發生變更,XOR 壓縮儲存空間配置使用的空間小於預設儲存空間配置 因為快照不會儲存完整的 4K 位元組快照大小縮減為 因為 XOR 資料包含許多零,壓縮比原始值更容易 封鎖資料在 Pixel 裝置上,XOR 壓縮可將快照大小縮減 25%, 40%。

如果是升級至 Android 13 以上版本的裝置,XOR 必須啟用壓縮功能詳情請參閱 XOR 壓縮率。

虛擬 A/B 壓縮程序

本節將詳細說明 Android 13 和 Android 12。

讀取中繼資料 (Android 12)

中繼資料是由 snapuserd Daemon 建構。中繼資料主要是 對應兩個 ID,每個 ID 各 8 個位元組,分別代表要合併的向量。 在 dm-snapshot 中則稱為 disk_exception

struct disk_exception {
    uint64_t old_chunk;
    uint64_t new_chunk;
};

將舊資料區塊取代為新的區塊時,就會使用磁碟例外狀況。

snapuserd Daemon 透過 COW 程式庫讀取內部 COW 檔案,並 會建立 COW 檔案中各項 COW 作業的中繼資料。

建立 dm- snapshot 裝置時,系統會從核心中的 dm-snapshot 啟動中繼資料讀取作業。

下圖提供中繼資料 IO 路徑的序列圖 但現在仍感到有點困難

序列圖、中繼資料的 IO 路徑
施工

圖 4. 中繼資料建構中的 IO 路徑序列流程

合併 (Android 12)

啟動程序完成後,更新引擎會將運算單元標示為開機 成功啟動,並藉由將 dm-snapshot 目標切換為 dm-snapshot-merge目標。

dm-snapshot 會逐步說明中繼資料,並為每個磁碟啟動合併 IO 例外狀況。以下將概略介紹合併 IO 路徑。

合併 IO 路徑

圖 5. 合併 IO 路徑總覽

如果裝置在合併過程中重新啟動,合併作業會在 接著重新啟動,合併完成

裝置對映圖層

如果裝置搭載 Android 13 以上版本, 會在虛擬 A/B 壓縮中執行快照和快照合併程序 snapuserd使用者空間元件。適用於升級至 Android 的裝置 13 以上版本,必須啟用這項功能。適用對象 詳細資料,請參閱使用者空間 merge

以下說明虛擬 A/B 壓縮程序:

  1. 架構會將 /system 分區從 dm-verity 裝置上掛接, 堆疊在 dm-user 裝置上方。也就是說 從根檔案系統轉送至 dm-user
  2. dm-user 會將 I/O 轉送至使用者空間 snapuserd Daemon I/O 要求
  3. 合併作業完成後,架構會在以下位置收合 dm-verity: 從 dm-linear 頂端 (system_base) 移除,並移除 dm-user

虛擬 A/B 壓縮
處理程序

圖 6. 虛擬 A/B 壓縮程序

快照合併程序可能會中斷。如果裝置於 合併程序,合併程序會在重新啟動後繼續執行。

Init 轉場效果

使用壓縮快照啟動時,必須啟動第一階段 init snapuserd,即可掛接分區。這會造成問題:載入 sepolicy 時 強制執行後,snapuserd 會放在錯誤的結構定義及其讀取要求中 未通過 Selinux 拒絕。

為解決這個問題,請在鎖定步驟中使用 init 進行 snapuserd 轉換,如下所示:

  1. 第一階段 init 從 ramdisk 啟動 snapuserd,並儲存開啟項目 檔案描述元。
  2. 第一階段 init 會將根檔案系統切換為系統分區, 然後執行 init 的系統副本。
  3. init 的系統副本會將合併的機構政策讀取為字串。
  4. Init 會在所有 ext4 支援的頁面上叫用 mlock()。然後停用全部 用於快照裝置的裝置對應資料表,並於 snapuserd 停止。之後 並禁止讀取分區資料,否則會導致死結。
  5. 使用開放式描述元至 snapuserd 的 ramdisk 副本,init 使用正確的 Sylinux 情境重新啟動 Daemon。裝置對應表 重新啟用。
  6. 叫用 munlockall(),您可以放心再次執行 IO。

聊天室使用情形

下表列出不同 OTA 的空間用量 採用 Pixel 作業系統和 OTA 大小的機制。

大小影響 非 A/B 版本 A 到 B 罩杯 虛擬 A/B 版本 虛擬 A/B (壓縮)
原始原廠映像檔 4.5 GB 超高 (3.8G 映像檔 + 7 億張保留空間)1 超高 9 GB (保留 3.8G + 7 億個運算單元) 超高 4.5 GB (3.8G 映像檔 + 7 億張空間) 超高 4.5 GB (3.8G 映像檔 + 7 億張空間)
其他靜態分區 /cache
在 OTA 期間取得額外儲存空間 (套用 OTA 後退回的空間) 1.4 GB /資料 0 3.8 GB2 /數據流量 2.1 GB2 /數據流量
套用 OTA 所需的儲存空間總量 5.9 GB3 (超能力和資料) 9 GB (超級) 8.3 GB3 (超能力和資料) 6.6 GB3 (超級容量與數據流量)

1 表示根據 Pixel 對應的假設版面配置。

2 假設新系統映像檔的大小與原始映像檔相同。

3在重新啟動前,聊天室需求是暫時的。

如要實作虛擬 A/B 或使用壓縮快照功能,請參閱 實作虛擬 A/B