Tổng quan về A/B ảo

Android có hai cơ chế cập nhật: cập nhật A/B (liền mạch) và cập nhật không phải A/B. Để giảm độ phức tạp của mã và cải thiện quá trình cập nhật, trong Android 11, hai cơ chế được hợp nhất thông qua A/B ảo để mang đến nội dung cập nhật liền mạch cho tất cả giúp giảm chi phí lưu trữ ở mức tối thiểu. Android 12 cung cấp tuỳ chọn nén A/B ảo để nén các phân vùng ảnh chụp nhanh. Trong cả Android 11 và Android 12, các lệnh sau đây áp dụng:

  • Cập nhật A/B ảo liền mạch như cập nhật A/B. Cập nhật A/B trực tuyến giảm thiểu thời gian thiết bị không có kết nối mạng và không sử dụng được.
  • Bạn có thể hoàn nguyên nội dung cập nhật A/B ảo. Nếu hệ điều hành mới không khởi động được, thiết bị tự động khôi phục về phiên bản trước đó.
  • Cập nhật A/B ảo sử dụng không gian bổ sung tối thiểu bằng cách chỉ sao chép phân vùng mà trình tải khởi động sử dụng. Các phân vùng có thể cập nhật khác là ảnh chụp nhanh.

Thông tin khái quát và thuật ngữ

Phần này định nghĩa các thuật ngữ và mô tả công nghệ hỗ trợ A/B ảo.

Trình liên kết thiết bị

Trình lập bản đồ thiết bị là một lớp khối ảo Linux được sử dụng thường xuyên trong Android. Bằng phân vùng động, các phân vùng như /system là một ngăn xếp gồm các thiết bị phân lớp:

  • Ở cuối ngăn xếp là phân vùng siêu thực (ví dụ: /dev/block/by-name/super).
  • Ở giữa là một thiết bị dm-linear, chỉ định khối nào trong lớp cha phân vùng tạo thành phân vùng đã cho. Tên này xuất hiện dưới dạng /dev/block/mapper/system_[a|b] trên thiết bị A/B hoặc /dev/block/mapper/system trên một thiết bị không phải là A/B.
  • Ở trên cùng là một thiết bị dm-verity, được tạo cho các phân vùng đã xác minh. Thiết bị này xác minh rằng các quy tắc chặn trên thiết bị dm-linear đã được ký chính xác. Nguồn dữ liệu này có tên là /dev/block/mapper/system-verity và là nguồn của điểm gắn /system.

Hình 1 cho thấy ngăn xếp dưới điểm gắn /system sẽ trông như thế nào.

Phân vùng xếp chồng bên dưới
hệ thống

Hình 1. Ngăn xếp dưới điểm gắn /system

ảnh chụp nhanh dm

A/B ảo dựa vào dm-snapshot, một mô-đun trình lập bản đồ thiết bị để chụp nhanh trạng thái của thiết bị lưu trữ. Khi sử dụng dm-snapshot, có 4 thiết bị trong phát:

  • Thiết bị cơ sở là thiết bị được chụp nhanh. Trên trang này, cơ sở thiết bị luôn là phân vùng động, chẳng hạn như hệ thống hoặc nhà cung cấp.
  • Thiết bị sao chép khi ghi (COW) để ghi nhật ký các thay đổi đối với thiết bị cơ sở. Nó có thể có kích thước bất kỳ nhưng phải đủ lớn để chứa mọi thay đổi đối với thiết bị cơ sở.
  • Thiết bị snapshot (ảnh chụp nhanh) được tạo bằng mục tiêu snapshot. Ghi vào được ghi vào thiết bị COW. Đọc từ bản tổng quan nhanh thiết bị đọc từ thiết bị cơ sở hoặc thiết bị COW, tuỳ thuộc vào liệu dữ liệu đang được truy cập có bị ảnh chụp nhanh thay đổi hay không.
  • Thiết bị origin được tạo bằng đích snapshot-origin. Đọc to thiết bị gốc sẽ đọc trực tiếp từ thiết bị cơ sở. Ghi vào nguồn gốc thiết bị ghi trực tiếp vào thiết bị cơ sở, nhưng dữ liệu gốc lại được sao lưu bằng cách ghi vào thiết bị COW.

Ánh xạ thiết bị cho
ảnh chụp nhanh dm

Hình 2. Ánh xạ thiết bị cho ảnh chụp nhanh dm

Ảnh chụp nhanh được nén

Trên Android 12 trở lên, vì yêu cầu về dung lượng trên phân vùng /data có thể cao, bạn có thể bật ảnh chụp nhanh được nén trong để giải quyết các yêu cầu cao hơn về không gian của phân vùng /data.

Ảnh chụp nhanh được nén bằng A/B ảo được xây dựng dựa trên các thành phần sau có trong Android 12 trở lên:

  • dm-user, một mô-đun nhân tương tự như FUSE cho phép không gian người dùng để triển khai các thiết bị khối.
  • snapuserd là một trình nền không gian người dùng để triển khai một ảnh chụp nhanh mới .

Các thành phần này cho phép nén. Các thay đổi cần thiết khác được thực hiện cho triển khai các khả năng tổng quan nhanh được nén được cung cấp trong các phần tiếp theo: Định dạng COW cho bản tổng quan nhanh nén, dm-userSnapuserd.

Định dạng COW cho bản tổng quan nhanh nén

Trong Android 12 trở lên, bản tổng quan nhanh nén sử dụng Định dạng COW. Tương tự như định dạng tích hợp sẵn của nhân, dùng không nén bản tổng quan nhanh, định dạng COW cho bản tổng quan nhanh nén có các phần xen kẽ siêu dữ liệu và dữ liệu. Siêu dữ liệu của định dạng gốc chỉ được phép cho thay thế Thao tác: Thay thế khối X trong hình ảnh gốc bằng nội dung của khối Y trong phần tổng quan nhanh. Định dạng COW của ảnh chụp nhanh nén sinh động hơn và hỗ trợ các thao tác sau:

  • Sao chép: Bạn nên thay thế khối X trong thiết bị cơ sở bằng khối Y trong thiết bị cơ sở.
  • Thay thế: Bạn nên thay khối X trong thiết bị cơ sở bằng nội dung của khối Y trong ảnh chụp nhanh. Mỗi khối này đều được nén gz.
  • 0: Bạn nên thay khối X trong thiết bị cơ sở bằng tất cả các số 0.
  • XOR: Thiết bị COW lưu trữ các byte nén XOR giữa khối X và khối Y. (Có trong Android 13 trở lên.)

Bản cập nhật OTA đầy đủ chỉ bao gồm các thao tác thay thếkhông. Gia tăng Ngoài ra, bản cập nhật OTA có thể có các hoạt động sao chép.

dm-user trong Android 12

Mô-đun nhân hệ điều hành dm-user cho phép userspace triển khai khối trình liên kết thiết bị thiết bị. Mục nhập bảng dm-người dùng tạo một thiết bị khác trong /dev/dm-user/<control-name>. Một quy trình userspace có thể thăm dò thiết bị để nhận yêu cầu đọc và ghi từ nhân. Mỗi yêu cầu có một vùng đệm cho không gian người dùng để điền sẵn (để đọc) hoặc truyền (để ghi).

Mô-đun nhân dm-user cung cấp một giao diện mới mà người dùng nhìn thấy cho nhân không phải là một phần của cơ sở mã kernel.org ngược dòng. Cho đến lúc đó, Google giữ quyền sửa đổi giao diện dm-user trong Android.

chụp nhanh

Thành phần không gian người dùng snapuserd để dm-user triển khai A/B ảo nén.

Trong phiên bản Virtual A/B không nén (trong Android 11 trở xuống, hoặc trong Android 12 mà không có tuỳ chọn ảnh chụp nhanh được nén), thiết bị COW là tệp thô. Khi tính năng nén được bật, các hàm COW thay vào đó là thiết bị dm-user được kết nối với một thực thể của Trình nền snapuserd.

Hạt nhân hệ điều hành không sử dụng định dạng COW mới. Vì vậy, thành phần snapuserd dịch các yêu cầu giữa định dạng Android COW và nhân hệ điều hành tích hợp sẵn định dạng:

Thành phần được kết nối nhanh dịch các yêu cầu giữa định dạng Android COW và nhân hệ điều hành
tích hợp sẵn
định dạng

Hình 3. Sơ đồ quy trình của snapuserd với vai trò là trình biên dịch giữa Android và Kernel Định dạng COW

Quá trình dịch và giải nén này không bao giờ diễn ra trên ổ đĩa. snapuserd thành phần chặn lượt đọc và ghi COW xảy ra trong nhân, và triển khai chúng bằng định dạng Android COW.

Nén bằng XOR

Đối với các thiết bị chạy Android 13 trở lên, Tính năng nén XOR (được bật theo mặc định) cho phép không gian người dùng để lưu trữ các byte nén XOR giữa các khối cũ và khối mới. Thời gian chỉ một vài byte trong một khối được thay đổi trong bản cập nhật A/B ảo, XOR lược đồ bộ nhớ nén sử dụng ít dung lượng hơn so với lược đồ bộ nhớ mặc định vì ảnh chụp nhanh không lưu trữ đầy đủ 4K byte. Việc giảm kích thước ảnh chụp nhanh này vì dữ liệu XOR chứa nhiều số 0 và dễ nén hơn so với dữ liệu thô chặn dữ liệu. Trên thiết bị Pixel, tính năng nén XOR giúp giảm 25% kích thước bản tổng quan nhanh để 40%.

Đối với các thiết bị nâng cấp lên Android 13 trở lên, XOR bạn phải bật tính năng nén. Để biết chi tiết, hãy xem XOR nén.

Quy trình nén A/B ảo

Phần này cung cấp thông tin chi tiết về quy trình nén A/B ảo được sử dụng trong Android 13 và Android 12.

Đọc siêu dữ liệu (Android 12)

Siêu dữ liệu được xây dựng bằng trình nền snapuserd. Siêu dữ liệu chủ yếu là ánh xạ hai mã nhận dạng, mỗi mã 8 byte đại diện cho các cung cần hợp nhất. Trong dm-snapshot, nó được gọi là disk_exception.

struct disk_exception {
    uint64_t old_chunk;
    uint64_t new_chunk;
};

Trường hợp ngoại lệ trên ổ đĩa được sử dụng khi một phần dữ liệu cũ được thay thế bằng một phần dữ liệu mới.

Một trình nền snapuserd đọc tệp COW nội bộ thông qua thư viện COW và tạo siêu dữ liệu cho từng hoạt động COW có trong tệp COW.

Quá trình đọc siêu dữ liệu được bắt đầu từ dm-snapshot trong nhân khi thiết bị dm- snapshot được tạo.

Hình dưới đây cung cấp một sơ đồ trình tự cho đường dẫn IO cho siêu dữ liệu xây dựng.

Sơ đồ trình tự, đường dẫn IO cho siêu dữ liệu
xây dựng

Hình 4. Luồng trình tự cho đường dẫn IO trong quá trình xây dựng siêu dữ liệu

Hợp nhất (Android 12)

Sau khi quá trình khởi động hoàn tất, công cụ cập nhật sẽ đánh dấu vị trí là khởi động thành công và bắt đầu hợp nhất bằng cách chuyển mục tiêu dm-snapshot thành Mục tiêu dm-snapshot-merge.

dm-snapshot xem qua siêu dữ liệu và bắt đầu nhập IO hợp nhất cho mỗi ổ đĩa ngoại lệ. Dưới đây là thông tin tổng quan cấp cao về đường dẫn IO hợp nhất.

Hợp nhất đường dẫn IO

Hình 5. Tổng quan về đường dẫn hợp nhất IO

Nếu thiết bị được khởi động lại trong quá trình hợp nhất, quá trình hợp nhất sẽ tiếp tục trên lần khởi động lại tiếp theo và quá trình hợp nhất hoàn tất.

Phân lớp trình liên kết thiết bị

Đối với các thiết bị chạy Android 13 trở lên, thực hiện quá trình hợp nhất ảnh chụp nhanh và ảnh chụp nhanh trong quá trình nén A/B ảo theo thành phần không gian người dùng snapuserd. Đối với các thiết bị nâng cấp lên Android 13 trở lên thì bạn phải bật tính năng này. Cho chi tiết, hãy xem Không gian người dùng hợp nhất.

Dưới đây là mô tả về quy trình nén A/B ảo:

  1. Khung này gắn phân vùng /system với thiết bị dm-verity, được xếp chồng lên trên thiết bị dm-user. Điều này có nghĩa là mỗi đợt I/O từ hệ thống tệp gốc được định tuyến đến dm-user.
  2. dm-user định tuyến I/O đến trình nền snapuserd của không gian người dùng. Trình này sẽ xử lý yêu cầu I/O.
  3. Khi thao tác hợp nhất hoàn tất, khung sẽ thu gọn dm-verity trên đầu dm-linear (system_base) và xoá dm-user.

Nén A/B ảo
quy trình

Hình 6. Quy trình nén A/B ảo

Quá trình hợp nhất ảnh chụp nhanh có thể bị gián đoạn. Nếu thiết bị khởi động lại trong khoảng thời gian quá trình hợp nhất, quá trình hợp nhất sẽ tiếp tục sau khi khởi động lại.

Chuyển đổi khởi tạo

Khi khởi động bằng ảnh chụp nhanh được nén, khởi động giai đoạn đầu tiên phải bắt đầu snapuserd để gắn các phân vùng. Việc này gây ra một sự cố: Khi sepolicy được tải và được thực thi, snapuserd bị đặt sai ngữ cảnh và các yêu cầu đọc thất bại với sự từ chối selinux.

Để giải quyết vấn đề này, hãy chuyển đổi snapuserd trong bước khoá bằng init như sau:

  1. init ở giai đoạn đầu tiên khởi chạy snapuserd từ ổ đĩa RAM và lưu một tệp đang mở tệp mô tả cho tệp đó trong biến môi trường.
  2. init giai đoạn đầu tiên chuyển hệ thống tệp gốc sang phân vùng hệ thống, sau đó thực thi bản sao hệ thống của init.
  3. Bản sao hệ thống của init đọc chính sách kết hợp thành một chuỗi.
  4. Init gọi mlock() trên mọi trang có hỗ trợ ext4. Sau đó, thao tác này sẽ huỷ kích hoạt tất cả bảng trình liên kết thiết bị cho các thiết bị chụp nhanh và dừng snapuserd. Sau này không được phép đọc trong các phân vùng vì việc này sẽ gây ra tắc nghẽn.
  5. Sử dụng chỉ số mô tả mở cho bản sao ramdisk của snapuserd, init chạy lại trình nền với ngữ cảnh selinux chính xác. Bảng trình liên kết thiết bị cho các thiết bị tổng quan nhanh được kích hoạt lại.
  6. Bắt đầu gọi munlockall() – có thể an toàn thực hiện lại IO.

Mức sử dụng dung lượng

Bảng sau đây so sánh mức sử dụng dung lượng của các OTA khác nhau các cơ chế sử dụng kích thước của hệ điều hành và OTA của Pixel.

Tác động đến kích thước không thuộc A/B A/B A/B ảo A/B ảo (nén)
Hình ảnh gốc về trạng thái ban đầu Super 4,5 GB (hình ảnh 3,8G + đặt trước 700 triệu)1 9GB siêu (dành riêng cho 3,8G + 700M, cho 2 khe cắm) Siêu 4,5 GB (hình ảnh 3,8G + đặt trước 700 triệu) Siêu 4,5 GB (hình ảnh 3,8G + đặt trước 700 triệu)
Phân vùng tĩnh khác /cache Không có Không có Không có
Bổ sung dung lượng lưu trữ trong thời gian OTA (trả lại dung lượng sau khi áp dụng OTA) 1,4 GB trên /dữ liệu 0 3,8 GB2 trên /dữ liệu 2,1 GB2 trên /dữ liệu
Tổng dung lượng lưu trữ cần thiết để áp dụng OTA 5,9 GB3 (siêu dữ liệu và dữ liệu) 9 GB (siêu) 8,3 GB3 (siêu dữ liệu và dữ liệu) 6,6 GB3 (siêu dữ liệu và dữ liệu)

1Cho biết bố cục được giả định dựa trên liên kết Pixel.

2Giả sử hình ảnh hệ thống mới có cùng kích thước với ảnh gốc.

3Yêu cầu về không gian sẽ được tạm thời xử lý cho đến khi khởi động lại.

Để triển khai A/B ảo hoặc sử dụng các tính năng tổng quan nhanh nén, hãy xem Triển khai A/B ảo