동적 링커는 트레블 VNDK 설계의 두 가지 문제점을 해결합니다.
- VNDK-SP 라이브러리를 비롯한 SP-HAL 공유 라이브러리 및 종속 항목이 프레임워크 프로세스에 로드되며, 기호 충돌 방지를 위한 메커니즘이 있어야 합니다.
dlopen()
및android_dlopen_ext()
는 빌드 시간에 표시되지 않고 정적 분석을 사용하여 감지하기 어려운 런타임 종속 항목을 도입할 수 있습니다.
이러한 두 가지 문제는 링커 네임스페이스 메커니즘으로 해결할 수 있습니다. 이 메커니즘은 동적 링커에서 제공합니다. 동적 링커는 라이브러리 이름은 같지만 기호는 다른 라이브러리가 충돌하지 않도록 여러 링커 네임스페이스의 공유 라이브러리를 격리할 수 있습니다.
반면 링커 네임스페이스 메커니즘은 유연하므로 링커 네임스페이스에서 일부 공유 라이브러리를 내보내고 다른 링커 네임스페이스에서 이러한 라이브러리를 사용할 수 있습니다. 내보낸 이러한 공유 라이브러리는 다른 프로그램에 공개되는 동시에 링커 네임스페이스 내에 구현 세부정보를 숨기는 애플리케이션 프로그래밍 인터페이스가 될 수 있습니다.
예를 들어 /system/lib[64]/libcutils.so
와 /system/lib[64]/vndk-sp-${VER}/libcutils.so
는 두 개의 공유 라이브러리입니다. 이 두 라이브러리의 기호는 서로 다를 수 있습니다. 이러한 라이브러리는 다른 링커 네임스페이스로 로드되므로 프레임워크 모듈이 /system/lib[64]/libcutils.so
에, SP-HAL 공유 라이브러리가 /system/lib[64]/vndk-sp-${VER}/libcutils.so
에 종속될 수 있습니다.
반면 /system/lib[64]/libc.so
는 링커 네임스페이스에서 내보내고 여러 링커 네임스페이스로 가져오는 공개 라이브러리의 예입니다. libnetd_client.so
와 같은 /system/lib[64]/libc.so
의 종속 항목은 /system/lib[64]/libc.so
가 상주하는 네임스페이스에 로드됩니다. 다른 네임스페이스는 이러한 종속 항목에 액세스할 수 없습니다. 이러한 메커니즘은 구현 세부정보를 캡슐화하는 동시에 공개 인터페이스를 제공합니다.
작동 원리
동적 링커는 DT_NEEDED
항목에 지정된 공유 라이브러리나 dlopen()
또는 android_dlopen_ext()
의 인수에 의해 지정된 공유 라이브러리를 로드하는 역할을 합니다. 두 경우 모두 동적 링커는 호출자가 있는 링커 네임스페이스를 찾고 종속 항목을 동일한 링커 네임스페이스에 로드하려고 합니다. 동적 링커가 공유 라이브러리를 지정된 링커 네임스페이스에 로드할 수 없으면 연결된 링커 네임스페이스에 내보낸 공유 라이브러리를 요청합니다.
구성 파일 형식
구성 파일 형식은 INI 파일 형식에 기반하며 일반적인 구성 파일은 다음과 같습니다.
dir.system = /system/bin dir.system = /system/xbin dir.vendor = /vendor/bin [system] additional.namespaces = sphal,vndk namespace.default.isolated = true namespace.default.search.paths = /system/${LIB} namespace.default.permitted.paths = /system/${LIB}/hw namespace.default.asan.search.paths = /data/asan/system/${LIB}:/system/${LIB} namespace.default.asan.permitted.paths = /data/asan/system/${LIB}/hw:/system/${LIB}/hw namespace.sphal.isolated = true namespace.sphal.visible = true namespace.sphal.search.paths = /odm/${LIB}:/vendor/${LIB} namespace.sphal.permitted.paths = /odm/${LIB}:/vendor/${LIB} namespace.sphal.asan.search.paths = /data/asan/odm/${LIB}:/odm/${LIB} namespace.sphal.asan.search.paths += /data/asan/vendor/${LIB}:/vendor/${LIB} namespace.sphal.asan.permitted.paths = /data/asan/odm/${LIB}:/odm/${LIB} namespace.sphal.asan.permitted.paths += /data/asan/vendor/${LIB}:/vendor/${LIB} namespace.sphal.links = default,vndk namespace.sphal.link.default.shared_libs = libc.so:libm.so namespace.sphal.link.vndk.shared_libs = libbase.so:libcutils.so namespace.vndk.isolated = true namespace.vndk.search.paths = /system/${LIB}/vndk-sp-29 namespace.vndk.permitted.paths = /system/${LIB}/vndk-sp-29 namespace.vndk.links = default namespace.vndk.link.default.shared_libs = libc.so:libm.so [vendor] namespace.default.isolated = false namespace.default.search.paths = /vendor/${LIB}:/system/${LIB}
구성 파일에는 다음이 포함됩니다.
- 동적 링커가 효과적인 섹션을 선택하게 하는 초반의 여러 디렉터리 섹션 매핑 속성
- 여러 링커 네임스페이스 구성 섹션:
- 각 섹션에는 여러 네임스페이스(그래프 꼭짓점)와 네임스페이스 간 다양한 대체 링크(그래프 원호)가 포함되어 있습니다.
- 각 네임스페이스에는 자체적인 격리, 검색 경로, 허용 경로, 공개 상태 설정이 포함됩니다.
아래 표에서는 각 속성의 의미에 관해 자세히 설명합니다.
디렉터리 섹션 매핑 속성
속성 | 설명 | 예 |
---|---|---|
|
각 속성이 디렉터리 아래의 실행 프로그램을 링커 네임스페이스 구성 섹션에 매핑합니다. |
|
관계 속성
속성 | 설명 | 예 |
---|---|---|
additional. |
섹션의 추가 네임스페이스( |
|
namespace. |
쉼표로 구분된 대체 네임스페이스 목록입니다. 현재 네임스페이스에서 공유 라이브러리를 찾을 수 없다면 동적 링커는 대체 네임스페이스에서 공유 라이브러리를 로드하려고 합니다. 목록 초반에 지정된 네임스페이스의 우선순위가 더 높습니다. |
공유 라이브러리나 실행 파일이 그런 다음 마지막으로 모든 시도에 실패하면 동적 링커가 오류를 반환합니다. |
namespace. |
공유 라이브러리를 이 속성은 |
대체 링크가 |
namespace. |
공유 라이브러리를 이 속성은 |
모든 라이브러리 이름이 |
네임스페이스 속성
속성 | 설명 | 예 |
---|---|---|
namespace. |
동적 링커가 공유 라이브러리 상주 위치를 확인해야 할지를 나타내는 부울 값입니다.
|
|
namespace. |
공유 라이브러리 검색을 위한 콜론으로 구분된 디렉터리 목록입니다.
예를 들어 |
동적 링커가 |
namespace. |
AddressSanitizer(ASan)가 사용 설정될 때 공유 라이브러리를 검색하기 위한 콜론으로 구분된 디렉터리 목록입니다. ASan이 사용 설정되면 |
ASan이 사용 설정되면 동적 링커가 먼저 |
namespace. |
|
예를 들어 |
namespace. |
ASan이 사용 설정되었을 때 동적 링커가 공유 라이브러리를 로드할 수 있는 콜론으로 구분된 디렉터리 목록입니다. ASan이 사용 설정되면 |
ASan이 사용 설정되면 |
namespace. |
|
|
링커 네임스페이스 생성
Android 11에서 링커 구성은 ${android-src}/system/core/rootdir/etc
의 일반 텍스트 파일을 사용하는 대신 런타임 시 /linkerconfig
아래에 생성됩니다. 구성은 런타임 환경에 기반하여 부팅 시간에 생성됩니다. 런타임 환경에는 다음 항목이 포함됩니다.
- 기기에서 VNDK를 지원하는 경우
- 공급업체 파티션의 타겟 VNDK 버전
- 제품 파티션의 VNDK 버전
- 설치된 APEX 모듈
링커 구성은 링커 네임스페이스 간 종속 항목을 결정하여 생성됩니다. 예를 들어 종속 항목 업데이트가 포함되어 있는 APEX 모듈에 업데이트가 있다면 이러한 변경사항을 반영하는 링커 구성이 생성됩니다. 링커 구성을 만드는 방법에 관한 자세한 내용은 ${android-src}/system/linkerconfig
에서 확인할 수 있습니다.
링커 네임스페이스 격리
세 가지 구성 유형이 있습니다. BoardConfig.mk
의 PRODUCT_TREBLE_LINKER_NAMESPACES
및 BOARD_VNDK_VERSION
값에 따라 상응하는 구성이 부팅 시간에 생성됩니다.
PRODUCT_TREBLE_ LINKER_NAMESPACES |
BOARD_VNDK_ VERSION |
선택된 구성 | VTS 요구사항 |
---|---|---|---|
true |
current |
VNDK |
Android 9 이상으로 출시되는 기기의 경우 필수입니다. |
비어 있음 | VNDK Lite |
Android 8.x로 출시되는 기기의 경우 필수입니다. | |
false |
비어 있음 | Legacy |
비 트레블 기기에 사용됩니다. |
VNDK Lite 구성은 SP-HAL 및 VNDK-SP 공유 라이브러리를 격리합니다. Android 8.0에서는 PRODUCT_TREBLE_LINKER_NAMESPACES
가 true
면 동적 링커의 구성 파일이어야 합니다.
VNDK 구성은 SP-HAL 및 VNDK-SP 공유 라이브러리도 격리합니다. 또한 이 구성은 전체 동적 링커 격리 기능을 제공하며, 시스템 파티션의 모듈과 공급업체 파티션의 공유 라이브러리가 서로에 종속되지 않도록 합니다.
Android 8.1 이상에서는 VNDK가 기본 구성이므로 BOARD_VNDK_VERSION
을 current
로 설정하여 전체 동적 링커 격리를 사용 설정할 것을 적극 권장합니다.
VNDK 구성
VNDK 구성은 시스템 파티션과 공급업체 파티션 간 공유 라이브러리 종속 항목을 격리합니다. 이전 하위 섹션에서 언급한 구성과 비교할 때 차이점은 다음과 같습니다.
-
프레임워크 프로세스
default
,vndk
,sphal
,rs
네임스페이스가 생성됩니다.- 모든 네임스페이스가 격리됩니다.
- 시스템 공유 라이브러리는
default
네임스페이스에 로드됩니다. - SP-HAL은
sphal
네임스페이스에 로드됩니다. - VNDK-SP 공유 라이브러리는
vndk
네임스페이스에 로드됩니다.
-
공급업체 프로세스
default
,vndk
,system
네임스페이스가 생성됩니다.default
네임스페이스가 격리됩니다.- 공급업체 공유 라이브러리는
default
네임스페이스에 로드됩니다. - VNDK 및 VNDK-SP 공유 라이브러리는
vndk
네임스페이스에 로드됩니다. - LL-NDK 및 종속 항목은
system
네임스페이스에 로드됩니다.
링커 네임스페이스 간의 관계는 아래에 나와 있습니다.
![VNDK 구성에 설명된 링커 네임스페이스 그래프](https://source.android.google.cn/static/docs/core/architecture/images/treble_vndk_linker_namespace3.png?authuser=19&hl=ko)
위의 그래프에서 LL-NDK 및 VNDK-SP는 다음과 같은 공유 라이브러리를 나타냅니다.
-
LL-NDK
libEGL.so
libGLESv1_CM.so
libGLESv2.so
libGLESv3.so
libandroid_net.so
libc.so
libdl.so
liblog.so
libm.so
libnativewindow.so
libneuralnetworks.so
libsync.so
libvndksupport.so
libvulkan.so
-
VNDK-SP
android.hardware.graphics.common@1.0.so
android.hardware.graphics.mapper@2.0.so
android.hardware.renderscript@1.0.so
android.hidl.memory@1.0.so
libRSCpuRef.so
libRSDriver.so
libRS_internal.so
libbase.so
libbcinfo.so
libc++.so
libcutils.so
libhardware.so
libhidlbase.so
libhidlmemory.so
libhidltransport.so
libhwbinder.so
libion.so
libutils.so
libz.so
기기의 /linkerconfig/ld.config.txt
에서 자세한 내용을 확인할 수 있습니다.
VNDK Lite 구성
Android 8.0부터 동적 링커는 SP-HAL 및 VNDK-SP 공유 라이브러리를 격리하도록 구성되므로 다른 프레임워크 공유 라이브러리와 기호가 충돌하지 않습니다. 링커 네임스페이스 간의 관계는 아래에 나와 있습니다.
![VNDK Lite 구성에 설명된 링커 네임스페이스 그래프](https://source.android.google.cn/static/docs/core/architecture/images/treble_vndk_linker_namespace1.png?authuser=19&hl=ko)
LL-NDK 및 VNDK-SP는 다음과 같은 공유 라이브러리를 나타냅니다.
-
LL-NDK
libEGL.so
libGLESv1_CM.so
libGLESv2.so
libc.so
libdl.so
liblog.so
libm.so
libnativewindow.so
libstdc++.so
(구성에 없음)libsync.so
libvndksupport.so
libz.so
(구성의 VNDK-SP로 이동됨)
-
VNDK-SP
android.hardware.graphics.common@1.0.so
android.hardware.graphics.mapper@2.0.so
android.hardware.renderscript@1.0.so
android.hidl.memory@1.0.so
libbase.so
libc++.so
libcutils.so
libhardware.so
libhidlbase.so
libhidlmemory.so
libhidltransport.so
libhwbinder.so
libion.so
libutils.so
아래 표에는 VNDK Lite 구성의 [system]
섹션에서 발췌한 프레임워크 프로세스의 네임스페이스 구성이 나열되어 있습니다.
네임스페이스 | 속성 | 값 |
---|---|---|
default |
search.paths |
/system/${LIB} /odm/${LIB} /vendor/${LIB} /product/${LIB}
|
isolated |
false |
|
sphal |
search.paths |
/odm/${LIB} /vendor/${LIB}
|
permitted.paths |
/odm/${LIB} /vendor/${LIB}
|
|
isolated |
true |
|
visible |
true |
|
links |
default,vndk,rs |
|
link.default.shared_libs |
LL-NDK | |
link.vndk.shared_libs |
VNDK-SP | |
link.rs.shared_libs |
libRS_internal.so |
|
vndk (VNDK-SP) |
search.paths |
/odm/${LIB}/vndk-sp /vendor/${LIB}/vndk-sp /system/${LIB}/vndk-sp-${VER}
|
permitted.paths |
/odm/${LIB}/hw /odm/${LIB}/egl /vendor/${LIB}/hw /vendor/${LIB}/egl /system/${LIB}/vndk-sp-${VER}/hw |
|
isolated |
true |
|
visible |
true |
|
links |
default |
|
link.default.shared_libs |
LL-NDK | |
rs (Renderscript) |
search.paths |
/odm/${LIB}/vndk-sp /vendor/${LIB}/vndk-sp /system/${LIB}/vndk-sp-${VER} /odm/${LIB} /vendor/${LIB}
|
permitted.paths |
/odm/${LIB} /vendor/${LIB} /data (컴파일된 RS 커널) |
|
isolated |
true |
|
visible |
true |
|
links |
default,vndk |
|
link.default.shared_libs |
LL-NDKlibmediandk.so libft2.so
|
|
link.vndk.shared_libs |
VNDK-SP |
아래 표에는 VNDK Lite 구성의 [vendor]
섹션에서 발췌한 공급업체 프로세스의 네임스페이스 구성이 표시되어 있습니다.
네임스페이스 | 속성 | 값 |
---|---|---|
default |
search.paths |
/odm/${LIB} /odm/${LIB}/vndk /odm/${LIB}/vndk-sp /vendor/${LIB} /vendor/${LIB}/vndk /vendor/${LIB}/vndk-sp /system/${LIB}/vndk-${VER} /system/${LIB}/vndk-sp-${VER} /system/${LIB} (지원 중단됨)/product/${LIB} (지원 중단됨) |
isolated |
false |
자세한 내용은 기기의 /linkerconfig/ld.config.txt
에서 확인할 수 있습니다.
문서 이력
Android 11 변경사항
- Android 11에서는 정적
ld.config.*.txt
파일이 코드베이스에서 삭제되고 LinkerConfig가 대신 런타임에 이 파일을 생성합니다.
Android 9 변경사항
- Android 9에서는
vndk
링커 네임스페이스가 공급업체 프로세스에 추가되고 VNDK 공유 라이브러리가 기본 링커 네임스페이스에서 격리됩니다. PRODUCT_FULL_TREBLE
을 좀 더 구체적인PRODUCT_TREBLE_LINKER_NAMESPACES
로 교체하세요.- Android 9에서는 다음과 같은 동적 링커 구성 파일의 이름이 변경됩니다.
Android 8.x Android 9 설명 ld.config.txt.in
ld.config.txt
런타임 링커 네임스페이스 격리를 포함하는 기기 ld.config.txt
ld.config.vndk_lite.txt
VNDK-SP 링커 네임스페이스 격리를 포함하는 기기 ld.config.legacy.txt
ld.config.legacy.txt
Android 7.x 이하를 실행하는 기존 기기 android.hardware.graphics.allocator@2.0.so
가 삭제됩니다.product
및odm
파티션이 추가됩니다.