Загрузить динамическую библиотеку
#include <dlfcn.h>void * dlopen( const char *pathname,int mode );
NULL
или путь к динамической библиотеке, которую необходимо загрузить.libc
Функция dlopen() предоставляет прямой доступ к средствам динамического связывания, делая доступным для вызывающего процесса исполняемый объектный файл, определенный в pathname. Она возвращает дескриптор, который можно использовать в последующих вызовах dlsym() и dlclose().
Функция dlopen() доступна только для процессов с динамическим связыванием. Процессы со статическим связыванием (те, с которыми libc связан статически) не могут вызывать dlopen(), так как статически связанный исполняемый файл:
|
Любые зависимости, отмеченные в объекте pathname, загружаются как часть вызова dlopen(). Эти зависимости ищутся в порядке загрузки для определения других дополнительных (рекурсивных) зависимостей. Данный процесс продолжается до полного удовлетворения всех зависимостей из pathname. Это дерево зависимостей называется группой.
Если аргумент pathname равен NULL
, dlopen() возвращает дескриптор глобального символьного объекта запущенного процесса. Это обеспечивает доступ к символам из исходного файла программного образа, из зависимостей, загруженных при запуске, а также к любым библиотекам, загруженным с помощью dlopen() с использованием флага RTLD_GLOBAL
. Этот набор символов может динамически изменяться, если приложение впоследствии вызовет dlopen() с флагом RTLD_GLOBAL
.
Вы можете использовать dlopen() любое количество раз для библиотек, чьи имена указывают на один и тот же абсолютный и относительный путь; данные каждой библиотеки загружаются в адресное пространство процесса только один раз.
Чтобы найти разделяемые библотеки, dlopen() выполняет поиск в следующем порядке:
LD_LIBRARY_PATH
_CS_LIBPATH
Следует помнить, что LD_LIBRARY_PATH
игнорируется, если для бинарного файла выставлен бит suid, и эффективный и фактический ID пользователя для бинарного файла не совпадают. Это сделано в целях безопасности.
Вышеуказанные директории настроены следующим образом:
|
Подробнее процесс загрузчи разделяемых библиотек, разрешения символов и их релокация описаны в статье Динамический загрузчик программ. |
При загрузке разделяемых библиотек приложение должно открывать конкретную версию библиотеки, а не ту, на которую указывает символическая ссылка.
Режим
Аргумент mode определяет, как dlopen() работает с путями при обработке релокаций, и управляет видимостью символов, найденных в pathname и зависимостях.
Аргумент mode - побитовое ИЛИ констант, описываемых ниже. Обратите внимание, что константы релоцирования и видимости взаимно исключают друг друга.
Релокации (relocation)
При загрузке с помощью функции dlopen() библиотека может содержать ссылки на символы, чьи адреса не известны до того, как библиотека не будет загружена; эти ссылки должны быть релоцированы (relocated) до непосредственного доступа к символам. Аргумент mode контролирует, когда это действие происходит, и может принимать одно из следующих значений:
Видимость
Следующие биты mode определяют область видимости символов, загруженных с помощью dlopen():
RTLD_WORLD
. Поиск символов с помощью dlopen( 0, mode ) и связанного с ним dlsym() также дают возможность найти символы библиотеки. Образ программы и другие библиотеки, загружаемые при старте программы, имеют режим mode RTLD_GLOBAL
; аргумент mode по умолчанию для библиотек, полученных с помощью dlopen() имеет значение RTLD_LOCAL
. Локальный объект может быть частью зависимостей более, чем одной группы; любая библиотека с mode, равным RTLD_LOCAL
, являющаяся зависимостью библиотеки с mode, равным RTLD_GLOBAL
, повышается до RTLD_GLOBAL
.
Объекты, загруженные с помощью dlopen(), которые требуют релоцирования глобальных символов, могут ссылаться на символы в любой библиотеке, открытой с RTLD_GLOBAL
.
Область символов
Следует использовать в качестве mode ИЛИ со следующими значениями, чтобы повлиять на область символов:
RTLD_GLOBAL
. Если не указать ни одного из этих значений, dlopen() использует RTLD_WORLD
| RTLD_GROUP
.
Если использовать RTLD_WORLD без RTLD_GROUP , dlopen() не загуржает никакие зависимости DLL. |
Остальные флаги
Следующие флаги предоставляют управление дополнительными свойствами:
Разрешение символов
При разрешении символов в разделяемой библиотеке компоновщик времени выполнения ищет их в таблице динамических символов в следующем порядке:
По умолчанию:
LD_PRELOAD
RTLD_GLOBAL
Когда установлена опция -Bsymbolic:
LD_PRELOAD
RTLD_GLOBAL
Для исполняемых файлов таблица динамических символов обычно содержит те символы, для которых известно, что они необходимы каким-либо разделяемым библиотекам. Это определяется компоновщиком во время связывания исполняемого файла с разделяемой библиотекой.
Поскольку во время загрузки разделяемой библиотеки с помощью функции dlopen() связывания не происходит, компоновщик не может определить, какие исполняемые символы необходимо сделать доступными для разделяемой библиотеки.
Если разделяемой библиотеке необходимо разрешить символы из исполняемого файла, можно запросить компоновщик сделать все символы исполняемого файла доступными для динамического связывания путем задания опции компоновщика -E. Например:
qcc -Vgcc_ntox86 -Wl,-E -o main main.o
Разделяемые библиотеки обычно размещают все свои символы в таблице динамических символов, поэтому данная опция не нужна при компоновке разделяемых библиотек. Для ограницения области видимости в динамических библиотеках могут применяться скрипты версионирования (version-scripts) и атрибуты видимости компилятора вроде attribute((visibility("default"))).
Дескриптор библиотеки или NULL
в случае ошибки.
Не следует как-то интерпретировать значение этого дескриптора. Например, при повторном открытии библиотеки не следует рассчитывать, что dlopen() вернет тот же дескриптор. |
При возникновении ошибок детальную информацию можно получить, используя функцию dlerror().
1
(единица) аналогично all. DL_DEBUG
. Если установлены и DL_DEBUG
, и LD_DEBUG
, DL_DEBUG
будет более приоритетной. POSIX 1003.1 X/Open Systems Interfaces Extension
Некоторые символы, определенные в исполняемых файлах или разделяемых библиотеках, могут быть недоступны компоновщику среды выполнения. Таблица символов, созданная ld для использования компоновщиком среды выполнения, может содержать подмножество символов, определенных в библиотеке.
Динамический загрузчик программ
procnto-*, dladdr(), dlclose(), dlerror(), dlsym()
ld, qcc в Справочнике по Утилитам
Предыдущий раздел: Описание API системной библиотеки