页面大小是 OS 管理内存的精细程度。如今,大多数 CPU 都支持 4 KB 页面大小,因此 Android OS 和应用曾经都是针对 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 内核。与 16 KB 内核搭配使用时,此配置会使用额外的内存,但可以提高系统性能。
将 Android 用户空间设置为 16 KB
只有内核为 16 KB 的 arm64
目标才支持 16 KB 页面。不过,还有一个在 x86_64
上为 Cuttlefish 模拟 16 KB 用户空间的选项。
对于 arm64
目标,如果您使用 Kleaf 构建内核,--page_size=16k
会以 16 KB 模式构建内核。如果您直接使用 Linux 内核配置,则可以通过设置 CONFIG_ARM64_16K_PAGES
(而非 CONFIG_ARM64_4K_PAGES
)来选择 16 KB 页面。
如需在 Android 用户空间中启用 16 KB 页面大小支持,请在您的产品上设置以下 build 选项:
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
会移除PAGE_SIZE
定义,并让组件在运行时确定页面大小。PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
,用于确保以 16 KB 对齐方式构建平台 ELF 文件。这种超出所需尺寸的大小是为了在未来实现兼容性。 采用 16 KB ELF 对齐方式后,内核可以支持 4 KB/16 KB 页面大小。
验证 build 标志
选择 lunch
目标后,请验证是否已在环境中正确设置 build 标志:
$ 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
如果前两个命令分别返回 16384
和 true
,则表示已正确设置 build 标志,以便与 16 KB 内核配合使用。不过,即使 build 通过了,也可能由于 16KB 环境中的差异而出现运行时问题。
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 项目的共享库,启用 16 KB 页面大小中的早期设置就足够了:
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 W(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 文件的对齐情况。