Жизненный цикл динамической библиотеки
Жизненный цикл динамической библиотеки включает следующие стадии:
- Загрузка в память.
Динамическая библиотека, скомпонованная с исполняемым файлом, загружается в разделяемую память при запуске процесса, созданного на основе этого исполняемого файла. Также процесс может загрузить динамическую библиотеку в разделяемую память вызовом функции
dlopen()
интерфейса POSIX. Динамическая библиотека может быть скомпонована с другими динамическими библиотеками, поэтому исполняемый файл зависит не только от непосредственно скомпонованной с ним динамической библиотеки, но и от всего графа зависимостей этой библиотеки. Динамическая библиотека загружается в разделяемую память совместно с всеми динамическими библиотеками, от которых зависит.Один экземпляр динамической библиотеки загружается в разделяемую память независимо от того, сколько процессов использует эту библиотеку. (Точнее, в разделяемую память загружается только часть динамической библиотеки, включающая код и доступные только на чтение данные. Другая часть динамической библиотеки загружается в память каждого процесса, который использует эту библиотеку.) Динамическая библиотека, от которой зависит нескольких других динамических библиотек, загружается в разделяемую память в единственном экземпляре.
Если задать через переменную окружения
LD_PRELOAD
список динамических библиотек, то эти динамические библиотеки будут загружены в разделяемую память, даже если исполняемый файл не зависит от них. (Элементами списка должны быть абсолютные или относительные пути к динамическим библиотекам, разделенные двоеточием, например:LD_PRELOAD=libmalloc.so:libfree.so:/usr/somepath/lib/libfoo.so
.) Функции, которые экспортируются динамическими библиотеками, указанными вLD_PRELOAD
, замещают одноименные функции, которые экспортируются другими динамическими библиотеками. Это можно использовать для целей отладки, если требуется подменить функции, импортируемые из динамических библиотек.Загрузчик динамических библиотек выполняет поиск динамических библиотек в следующем порядке:
- По абсолютным путям, заданным через переменную окружения
LD_LIBRARY_PATH
.Пути должны быть разделены двоеточием, например:
LD_LIBRARY_PATH=/usr/lib:/home/user/lib
. - По абсолютным путям, заданным в поле
DT_RUNPATH
илиDT_RPATH
секции.dynamic
исполняемых файлов и динамических библиотек.При компоновке исполняемых файлов и динамических библиотек могут быть заданы пути, по которым загрузчик динамических библиотек будет выполнять поиск. (Это можно сделать, например, через свойство
INSTALL_RPATH
вCMake
-командеset_target_properties()
.) Пути для поиска динамических библиотек сохраняются в полеDT_RUNPATH
илиDT_RPATH
секции.dynamic
. Это поле может быть как в исполняемых файлах, скомпонованных с динамическими библиотеки, так и в самих динамических библиотеках, скомпонованных с другими динамическими библиотеками. - По пути
/lib
.
Загрузчик динамических библиотек выполняет поиск в том же порядке, если в параметре
filename
функцииdlopen()
или в переменной окруженияLD_PRELOAD
указан относительный путь к динамической библиотеке. Если указан абсолютный путь, то загрузчик помещает динамическую библиотеку в разделяемую память без выполнения поиска. - По абсолютным путям, заданным через переменную окружения
- Использование процессом (процессами).
- Выгрузка из памяти.
Динамическая библиотека выгружается из разделяемой памяти, когда все процессы, использующие эту библиотеку, завершились или вызвали функцию
dlclose()
интерфейса POSIX. Динамическая библиотека, скомпонованная с исполняемым файлом, не может быть выгружена из разделяемой памяти до завершения процесса, который был создан на основе этого исполняемого файла. Динамическая библиотека, скомпонованная с другими динамическими библиотеками, выгружается из разделяемой памяти после выгрузки всех библиотек, которые зависят от нее.