페이지 크기는 OS가 메모리를 관리하는 세부사항입니다. 오늘날 대부분의 CPU는 4KB 페이지 크기를 지원하므로 Android OS 및 앱은 이전부터 4KB 페이지 크기로 실행되도록 빌드되고 최적화되었습니다. ARM CPU는 더 큰 16KB 페이지 크기를 지원하며 Android 15부터 AOSP는 16KB 페이지 크기로 Android를 빌드하는 기능도 지원합니다. 이 옵션은 추가 메모리를 사용하지만 시스템 성능을 향상시킵니다. Android 15부터 이 옵션은 기본적으로 사용 설정되지 않지만 OEM 및 앱 개발자가 향후 모든 위치에서 16KB 모드로 전환할 준비를 할 수 있도록 개발자 모드 또는 개발자 옵션으로 사용할 수 있습니다.
Android 15 이상에서는 16KB ELF 정렬을 사용하여 Android를 빌드할 수 있습니다. 이 정렬은 android14-6.1
부터 시작하는 4KB 및 16KB 커널에서 작동합니다.
이 구성은 16KB 커널과 함께 사용하면 추가 메모리를 사용하지만 시스템 성능을 개선합니다.
Android 사용자 공간을 16KB로 설정
16KB 페이지는 16KB 커널이 있는 arm64
타겟에서만 지원됩니다.
그러나 Cuttlefish에서 사용할 수 있는 x86_64
의 16KB 사용자 공간 시뮬레이션 옵션도 있습니다.
arm64
타겟의 경우 Kleaf를 사용하여 커널을 빌드하면 --page_size=16k
가 16KB 모드로 커널을 빌드합니다.
Linux 커널 구성을 직접 사용하는 경우 CONFIG_ARM64_4K_PAGES
대신 CONFIG_ARM64_16K_PAGES
를 설정하여 16KB 페이지를 선택할 수 있습니다.
Android 사용자 공간에서 16KB 페이지 크기 지원을 사용 설정하려면 제품에서 다음 빌드 옵션을 설정하세요.
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
는PAGE_SIZE
정의를 삭제하며, 구성 요소가 런타임에 페이지 크기를 결정하도록 합니다.PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
는 플랫폼 ELF 파일이 16KB 정렬로 빌드되도록 합니다. 필요 이상으로 큰 크기는 향후의 호환성을 고려한 것입니다. 16KB ELF 정렬을 사용하면 커널이 4KB/16KB 페이지 크기를 지원할 수 있습니다.
빌드 플래그 확인
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
가 반환되면 빌드 플래그가 16KB 커널에서 작동하도록 올바르게 설정된 것입니다. 그러나 빌드가 통과하더라도 16KB 환경의 차이로 인해 런타임 문제가 발생할 수 있습니다.
16KB 페이지 크기 시스템 프로그래밍
Android 지원 기기의 대부분의 코드는 페이지 크기를 직접 처리하지 않습니다. 하지만 페이지를 다루는 코드의 경우 커널의 메모리 할당 동작이 변경되므로 호환성뿐만 아니라 최대 성능과 최소 리소스 사용량을 갖는 코드를 작성하려면 이 점을 염두에 두어야 합니다.
4KB 시스템에서 1KB, 2KB 또는 최대 4KB 영역에서 mmap
를 호출하면 시스템은 이를 구현하기 위해 4KB를 예약합니다. 즉, 커널에 메모리를 요청할 때 커널은 항상 요청된 메모리를 가장 가까운 페이지 크기로 올림해야 합니다. 예를 들어 4KB 영역에 5KB 영역을 할당하면 커널은 8KB를 할당합니다.
16KB 커널에서는 이러한 추가 페이지 '꼬리 부분'이 더 큽니다. 예를 들어 1KB에서 5KB까지의 모든 할당은 16KB 커널과 함께 사용하면 16KB를 할당합니다. 17KB를 요청하면 32KB가 할당됩니다.
예를 들어 4KB 시스템에서는 4KB 읽기 쓰기 익명 영역 2개를 할당해도 됩니다. 그러나 16KB 커널에서는 페이지 2개 또는 32KB가 할당됩니다. 16KB 커널에서는 가능하면 이러한 리전을 단일 읽기 또는 쓰기 가능한 페이지로 결합하여 16KB만 사용되도록 할 수 있으므로 4KB 커널 사례에 비해 8KB가 낭비됩니다. 메모리 사용량을 더 줄이려면 더 많은 페이지를 결합할 수 있습니다. 실제로 최대한 최적화된 16KB 시스템에서는 페이지 테이블이 동일한 메모리의 4분의 1 크기이므로 16KB 페이지에 4KB 시스템보다 메모리가 적게 필요합니다.
mmap
를 사용할 때마다 요청하는 크기를 가장 가까운 페이지 크기로 반올림해야 합니다. 이렇게 하면 커널이 할당하는 전체 메모리가 암시적으로 요청되고 암시적으로 또는 실수로 액세스할 수 있는 대신 런타임 값에서 사용자 공간에 직접 표시됩니다.
16KB ELF 정렬로 공유 라이브러리 빌드
Android 프로젝트에 포함된 공유 라이브러리를 빌드하려면 16KB 페이지 크기 사용 설정의 이전 설정이면 충분합니다.
PRODUCT_NO_BIONIC_PAGE_SIZE_MACRO := true
PRODUCT_MAX_PAGE_SIZE_SUPPORTED := 16384
Android 프로젝트에 포함되지 않은 공유 라이브러리를 빌드하려면 다음 링커 플래그를 전달해야 합니다.
-Wl,-z,max-page-size=16384
바이너리 및 사전 빌드의 16KB ELF 정렬 확인
정렬 및 런타임 동작을 확인하는 가장 좋은 방법은 16KB 컴파일된 커널에서 테스트하고 실행하는 것입니다. 하지만 문제를 더 일찍 포착하려면 다음 단계를 따르세요.
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
를 사용하여 일시적으로 무시합니다. 이 설정은 모든 사전 빌드를 확인하고 사전 빌드가 업데이트되었지만 16KB로 정렬되지 않은 경우 이를 감지할 수 있도록 합니다.Android 15 이상으로 실행되는 기기에서 기기 내 ELF 파일의 정렬을 확인하는
atest elf_alignment_test
를 실행할 수 있습니다.