Размер страницы — это гранулярность, с которой ОС управляет памятью. Большинство современных ЦП поддерживают размер страницы 4 КБ, поэтому ОС Android и приложения исторически создавались и оптимизировались для работы с размером страницы 4 КБ. ЦП ARM поддерживают больший размер страницы 16 КБ, а начиная с Android 15, AOSP также поддерживает сборку Android с размером страницы 16 КБ. Эта опция использует дополнительную память, но повышает производительность системы. Начиная с Android 15, эта опция не включена по умолчанию, но она доступна как режим разработчика или опция разработчика для OEM-производителей и разработчиков приложений, чтобы подготовиться к переходу на режим 16 КБ повсеместно в будущем.
Android 15 и выше поддерживают сборку Android с выравниванием ELF 16 КБ, которое работает с ядрами 4 КБ и 16 КБ, начиная с android14-6.1
. При использовании с ядром 16 КБ эта конфигурация использует дополнительную память, но повышает производительность системы.
Установить размер пользовательского пространства Android на 16 КБ
Страницы размером 16 КБ поддерживаются только на arm64
целях с ядрами размером 16 КБ. Однако есть также возможность симулировать пользовательское пространство размером 16 КБ на x86_64
для Cuttlefish.
Для целей arm64
, если вы используете Kleaf для сборки ядра, --page_size=16k
собирает ядро в режиме 16 КБ. Если вы напрямую используете конфигурацию ядра Linux, вы можете выбрать страницы размером 16 КБ, установив CONFIG_ARM64_16K_PAGES
вместо CONFIG_ARM64_4K_PAGES
.
Чтобы включить поддержку размера страницы 16 КБ в пользовательском пространстве Android, установите следующие параметры сборки вашего продукта:
-
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
удаляет определениеPAGE_SIZE
и заставляет компоненты определять размер страницы во время выполнения. -
PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
, что гарантирует, что файлы ELF платформы будут построены с выравниванием 16 КБ. Этот размер больше необходимого нужен для будущей совместимости. С выравниванием ELF 16 КБ ядро может поддерживать размеры страниц 4 КБ/16 КБ.
Проверить флаги сборки
После выбора цели 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
Если предыдущие две команды возвращают 16384
и true
соответственно, ваши флаги сборки настроены правильно для работы с ядром 16 КБ. Однако даже если сборка пройдет успешно, все равно могут возникнуть проблемы во время выполнения из-за различий в среде 16 КБ.
Системное программирование размером страницы 16 КБ
Подавляющее большинство кода на любом устройстве Android напрямую не работает с размером страницы. Однако для кода, который работает со страницами, поведение распределения памяти ядра меняется, и вам нужно иметь это в виду, чтобы писать код, который не только совместим, но и максимально производительен и минимально ресурсоемок.
Если вы вызываете mmap
для области размером 1 КБ, 2 КБ или до 4 КБ в системе размером 4 КБ, система резервирует 4 КБ для реализации этого. Другими словами, при запросе памяти из ядра ядро всегда должно округлять запрашиваемую память до ближайшего размера страницы. Например, если вы выделяете область размером 5 КБ в области размером 4 КБ, ядро выделяет 8 КБ.
На ядре 16 КБ эти дополнительные "хвосты" страниц больше. Например, все эти выделения от 1 КБ до 5 КБ выделят 16 КБ при использовании с ядром 16 КБ. Если вы запросите 17 КБ, оно выделит 32 КБ.
Например, в системе 4 КБ можно выделить два анонимных региона чтения-записи по 4 КБ. Однако в ядре 16 КБ это приведет к выделению двух страниц или 32 КБ. В ядре 16 КБ, если это возможно, эти регионы можно объединить в одну страницу чтения или записи, так что будет использоваться только 16 КБ, тратя 8 КБ по сравнению со случаем ядра 4 КБ. Чтобы еще больше сократить использование памяти, можно объединить больше страниц. Фактически, в системе 16 КБ, которая максимально оптимизирована, страницы 16 КБ требуют меньше памяти, чем системы 4 КБ, потому что таблица страниц составляет одну четвертую размера для той же памяти.
При использовании mmap
убедитесь, что вы округляете запрашиваемый размер до ближайшего размера страницы. Это гарантирует, что весь объем памяти, выделяемой ядром, будет напрямую виден пользовательскому пространству в значениях времени выполнения, а не будет неявно запрошен и неявно или случайно доступен.
Создание общих библиотек с выравниванием ELF размером 16 КБ
Для создания общих библиотек, являющихся частью проекта Android , достаточно предыдущих настроек в разделе «Включить размер страницы 16 КБ» :
-
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
-
PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
Чтобы собрать общие библиотеки, которые не являются частью проекта Android , вам необходимо передать этот флаг компоновщика:
-Wl,-z,max-page-size=16384
Проверка двоичных файлов и готовых сборок на соответствие 16 КБ ELF
Лучший способ проверить выравнивание и поведение во время выполнения — это протестировать и запустить на скомпилированном ядре размером 16 КБ. Однако, чтобы обнаружить некоторые проблемы раньше:
Начиная с Android 16, вы можете задать
PRODUCT_CHECK_PREBUILT_MAX_PAGE_SIZE := true
во время сборки. Используйтеignore_max_page_size: true
вAndroid.bp
иLOCAL_IGNORE_MAX_PAGE_SIZE := true
вAndroid.mk
, чтобы временно игнорировать их. Эти настройки проверяют все предварительные сборки и позволяют обнаружить, когда одна из них обновлена, но не выровнена по 16 КБ.Вы можете запустить
atest elf_alignment_test
, который проверяет выравнивание файлов ELF на устройствах с Android 15 и более поздними версиями.