Динамический компоновщик решает две проблемы в дизайне 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 | Для не-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 изолирует зависимости общей библиотеки между системным разделом и разделами поставщика. По сравнению с конфигурациями, упомянутыми в предыдущем подразделе, отличия заключаются в следующем:
- Рамочные процессы -  создаются пространства имен default,vndk,sphalиrs.
- Все пространства имен изолированы.
-  Системные общие библиотеки загружаются в пространство имен по default.
-  SP-HAL загружаются в пространство имен sphal.
-  Общие библиотеки VNDK-SP загружаются в пространство имен vndk.
 
-  создаются пространства имен 
- Процессы поставщика -  создаются пространства имен default,vndkиsystem.
-  Пространство имен defaultизолировано.
-  Общие библиотеки поставщиков загружаются в пространство имен по default.
-  Общие библиотеки VNDK и VNDK-SP загружаются в пространство имен vndk.
-  LL-NDK и его зависимости загружаются в systemпространство имен.
 
-  создаются пространства имен 
Отношения между пространствами имен компоновщика показаны ниже.

На изображении выше 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 устройства.
Конфигурация ВНДК Лайт
Начиная с 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(для ВНДК-СП) | 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.х Андроид 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.
