Динамический компоновщик решает две проблемы, возникающие при проектировании Treble VNDK:
- Разделяемые библиотеки SP-HAL и их зависимости, включая библиотеки VNDK-SP, загружаются в процессы фреймворка. Должны существовать механизмы для предотвращения конфликтов символов.
- Функции
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 — это пример общедоступной библиотеки, которая экспортируется пространством имен компоновщика и импортируется во многие пространства имен компоновщика. Зависимости /system/lib[64]/libc.so , такие как libnetd_client.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. namespaces | Разделенный запятыми список дополнительных пространств имен (в дополнение к пространству имен | Это указывает на то, что в конфигурации |
namespace. name . links | Список резервных пространств имен, разделенных запятыми. Если разделяемая библиотека не найдена в текущем пространстве имен, динамический компоновщик пытается загрузить ее из резервных пространств имен. Пространство имен, указанное в начале списка, имеет более высокий приоритет. | Если разделяемая библиотека или исполняемый файл запрашивает разделяемую библиотеку, которую невозможно загрузить в пространство имен А затем, если разделяемую библиотеку не удается загрузить и из пространства имен Наконец, если все попытки окажутся неудачными, динамический компоновщик вернет ошибку. |
namespace. name . link. other . shared_libs | Список разделяемых библиотек, разделенных двоеточиями, которые можно искать в Это свойство нельзя использовать с | Это означает, что резервная компоновка принимает в качестве запрошенного имени библиотеки только |
namespace. name . link. other . allow_all_shared_libs | Логическое значение, указывающее, можно ли выполнить поиск всех разделяемых библиотек в Это свойство нельзя использовать с | Это означает, что все имена библиотек могут передаваться по резервной ссылке из пространства имен |
Свойства пространства имён
| Свойство | Описание | Пример |
|---|---|---|
namespace. name . isolated | Логическое значение, указывающее, следует ли динамическому компоновщику проверять местоположение разделяемой библиотеки. Если Если | Это означает, что в пространство имен |
namespace. name . search.paths | Список каталогов, разделённых двоеточиями, для поиска общих библиотек. Указанные в Если Например, если | Это означает, что динамический компоновщик ищет разделяемые библиотеки в каталоге |
namespace. name . asan.search.paths | Список каталогов, разделенных двоеточиями, для поиска разделяемых библиотек при включенном AddressSanitizer (ASan) . | Это означает, что при включении ASan динамический компоновщик сначала выполняет поиск в |
namespace. name . permitted.paths | Список каталогов (включая подкаталоги), разделённых двоеточиями, куда динамический компоновщик может загружать разделяемые библиотеки (в дополнение к Можно также загрузить разделяемые библиотеки, находящиеся в подкаталогах Если | Это означает, что разделяемые библиотеки в каталоге Например, без |
namespace. name . asan.permitted.paths | Список каталогов, разделённых двоеточиями, куда динамический компоновщик может загружать разделяемые библиотеки при включенной функции ASan . | Это означает, что при включении ASan общие библиотеки, расположенные в |
namespace. name . visible | Логическое значение, указывающее, может ли программа (кроме Если Если | Это означает, что |
Создание пространства имен компоновщика
В Android 11 конфигурация компоновщика создается во время выполнения в каталоге /linkerconfig вместо использования обычных текстовых файлов в ${android-src}/system/core/rootdir/etc . Конфигурация генерируется во время загрузки на основе среды выполнения и включает следующие элементы:
- Если устройство поддерживает VNDK
- Целевая версия VNDK для раздела поставщика
- Версия VNDK для раздела продукта
- Установлены модули APEX
Конфигурация компоновщика создается путем разрешения зависимостей между пространствами имен компоновщика. Например, если в модулях APEX есть обновления, включающие изменения зависимостей, генерируется конфигурация компоновщика, отражающая эти изменения. Более подробную информацию о создании конфигурации компоновщика можно найти в ${android-src}/system/linkerconfig .
изоляция пространства имен компоновщика
Существует три типа конфигурации. В зависимости от значений параметров PRODUCT_TREBLE_LINKER_NAMESPACES и BOARD_VNDK_VERSION в BoardConfig.mk , соответствующая конфигурация генерируется во время загрузки.
PRODUCT_TREBLE_LINKER_NAMESPACES | BOARD_VNDK_VERSION | Выбранная конфигурация | Требования VTS |
|---|---|---|---|
true | current | VNDK | Обязательно для устройств, выпущенных под управлением Android 9 или выше. |
| Пустой | VNDK Lite | Обязательно для устройств, выпущенных с Android 8.x. | |
false | Пустой | Legacy | Для устройств без поддержки Treble |
Конфигурация 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пространство имен.
- Создаются пространства имен
Взаимосвязь между пространствами имен компоновщика показана ниже.

Рисунок 1. Изоляция пространства имен компоновщика (конфигурация VNDK).
На изображении выше LL-NDK и VNDK-SP обозначают следующие разделяемые библиотеки:
- ЛЛ-НДК
-
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
-
- ВНДК-СП
-
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 таким образом, чтобы их символы не конфликтовали с другими разделяемыми библиотеками фреймворка. Взаимосвязь между пространствами имен компоновщика показана ниже.

LL-NDK и VNDK-SP обозначают следующие разделяемые библиотеки:
- ЛЛ-НДК
-
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 в конфигурации)
-
- ВНДК-СП
-
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
-
В таблице ниже приведена конфигурация пространств имен для процессов фреймворка, взятая из раздела [system] в конфигурации VNDK Lite.
| Пространство имен | Свойство | Ценить |
|---|---|---|
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 | ЛЛ-НДК | |
link.vndk.shared_libs | ВНДК-СП | |
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 | ЛЛ-НДК | |
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 | ЛЛ-НДКlibmediandk.solibft2.so | |
link.vndk.shared_libs | ВНДК-СП |
В таблице ниже представлена конфигурация пространств имен для процессов поставщика, взятая из раздела [vendor] в конфигурации VNDK Lite.
| Пространство имен | Свойство | Ценить |
|---|---|---|
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.inld.config.txtДля устройств с изоляцией пространства имен компоновщика во время выполнения ld.config.txtld.config.vndk_lite.txtДля устройств с изоляцией пространства имен компоновщика VNDK-SP ld.config.legacy.txtld.config.legacy.txtДля устаревших устройств под управлением Android 7.x или более ранних версий. - Удалите
android.hardware.graphics.allocator@2.0.so. - Добавлены разделы
productиodm.