Динамический компоновщик решает две задачи при проектировании 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 | Выбранная конфигурация | Требование СУДС | 
|---|---|---|---|
 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пространство имен. 
-  Создаются пространства имен 
 
Взаимосвязь между пространствами имен компоновщика проиллюстрирована ниже.

Рисунок 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 изменяет названия следующих файлов конфигурации динамического компоновщика.
Андроид 8.x Андроид 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.