頁面大小 16 KB

頁面大小是作業系統管理記憶體的細緻度。目前大多數的 CPU 都支援 4 KB 分頁大小,因此 Android 作業系統和應用程式一向都是以 4 KB 分頁大小建構及最佳化。ARM CPU 支援較大的 16 KB 分頁大小,從 Android 15 開始,AOSP 也支援以 16 KB 分頁大小建構 Android。這個選項會使用額外記憶體,但可改善系統效能。自 Android 15 起,這個選項預設為停用狀態,但可做為開發人員模式或開發人員選項,供 OEM 和應用程式開發人員準備在日後將所有位置切換為 16 KB 模式。

Android 15 以上版本支援使用 16 KB ELF 對齊方式建構 Android,可搭配 4 KB 和 16 KB 核心 (自 android14-6.1 起) 搭配使用。搭配 16 KB 核心使用時,此設定會使用額外記憶體,但可提升系統效能。

將 Android 使用者空間設為 16 KB

16 KB 頁面僅支援 arm64 目標,且核心必須為 16 KB。不過,您也可以x86_64 上模擬 16 KB 的使用者空間,以便測試 Cuttlefish。

針對 arm64 目標,如果您使用 Kleaf 建構核心,--page_size=16k 會以 16 KB 模式建構核心。如果您直接使用 Linux 核心設定,可以設定 CONFIG_ARM64_16K_PAGES 而非 CONFIG_ARM64_4K_PAGES,選取 16 KB 的頁面。

如要在 Android 使用者空間中啟用 16 KB 頁面大小支援功能,請在產品上設定下列建構選項:

  • PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true 會移除 PAGE_SIZE 定義,並讓元件在執行階段決定網頁大小。
  • PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384,可確保平台 ELF 檔案以 16 KB 對齊方式建構。這個大於所需大小的值是為了日後的相容性。使用 16 KB ELF 對齊功能,核心可支援 4 KB/16 KB 頁面大小。

驗證建構旗標

選取 lunch 目標後,請確認建構標記是否已在環境中正確設定:

$ source build/envsetup.sh
$ lunch target

$ get_build_var TARGET_MAX_PAGE_SIZE_SUPPORTED
16384
$ get_build_var TARGET_NO_BIONIC_PAGE_SIZE_MACRO
true

如果前述兩個指令分別傳回 16384true,表示您已正確設定建構標記,可搭配 16 KB 核心運作。不過,即使建構作業通過,仍可能因 16 KB 環境的差異而發生執行階段問題。

16 KB 頁面大小系統編程

任何 Android 裝置上的程式碼幾乎都不會直接處理網頁大小。不過,對於處理頁面的程式碼,核心的記憶體配置行為會有所變更,因此您必須將這點牢記在心,才能編寫出不僅相容,且效能最高、資源消耗最少的程式碼。

如果您在 4 KB 系統上,在 1 KB、2 KB 或最多 4 KB 區域中呼叫 mmap,系統會保留 4 KB 來實作這項操作。換句話說,當您向核心要求記憶體時,核心必須一律將要求的記憶體四捨五入至最接近的頁面大小。舉例來說,如果您在 4 KB 區域上配置 5 KB 區域,核心會配置 8 KB。

在 16 KB 核心中,這些頁面的額外「尾端」會較大。舉例來說,如果使用 16 KB 核心,從 1 KB 到 5 KB 的所有配置都會分配 16 KB。如果您要求 17 KB,系統會分配 32 KB。

舉例來說,在 4 KB 系統上,您可以分配兩個 4 KB 讀寫匿名區域。不過,在 16 KB 核心上,這會導致系統分配兩個頁面或 32 KB。在 16 KB 核心中,如果可能,這些區域可以合併為單一可讀或可寫頁面,這樣只會使用 16 KB,相較於 4 KB 核心,這會浪費 8 KB。如要進一步減少記憶體用量,可以合併更多頁面。事實上,在經過充分最佳化的 16 KB 系統中,16 KB 分頁所需的記憶體比 4 KB 系統少,因為分頁表的大小只有相同記憶體的四分之一。

使用 mmap 時,請務必將要求的大小向上捨入至最接近的頁面大小。這樣一來,使用者空間就能直接在執行階段值中看到核心分配的記憶體總量,而非隱含要求並隱含或意外存取。

使用 16 KB ELF 對齊方式建構共用程式庫

如要建構 android 專案中的共用程式庫,只要先前在「Enable 16 KB page size」中設定的內容就足夠了:

  • PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
  • PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384

如要建構不屬於 Android 專案的共用程式庫,您必須傳遞這個連結器標記:

-Wl,-z,max-page-size=16384

驗證二進位檔和預先建構的 16 KB ELF 對齊

如要驗證對齊和執行階段行為,最佳做法是在 16 KB 編譯的核心上進行測試和執行。不過,為了提早發現某些問題,請採取下列做法:

  • 從 Android 16 (AOSP 實驗版) 開始,您可以在建構期間設定 PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true。請在 Android.bp 中使用 ignore_max_page_size: true,在 Android.mk 中使用 LOCAL_IGNORE_MAX_PAGE_SIZE := true,暫時忽略這些元素。這些設定可驗證所有預先建構的內容,並讓您偵測何時更新其中一個內容,但未對齊 16 KB。

  • 您可以執行 atest elf_alignment_test,該工具會在搭載 Android 15 以上版本的裝置上,驗證裝置端 ELF 檔案的對齊情形。