Жизненный цикл динамической библиотеки включает следующие стадии:
Динамическая библиотека, скомпонованная с программой, загружается в память при запуске процесса, в контексте которого эта программа исполняется. Запущенный процесс может загрузить динамическую библиотеку в память вызовом функции dlopen()
интерфейса POSIX. Динамическая библиотека может быть скомпонована с другими динамическими библиотеками, поэтому программа зависит не только от непосредственно скомпонованной с ней динамической библиотеки, но и от всего графа зависимостей этой библиотеки. Динамическая библиотека загружается в память совместно с всеми динамическими библиотеками, от которых зависит.
Если системная программа BlobContainer
включена в решение на базе KasperskyOS, то один экземпляр динамической библиотеки загружается в разделяемую память независимо от того, сколько процессов использует эту библиотеку. (Точнее, в разделяемую память загружается только часть динамической библиотеки, включающая код и доступные только на чтение данные. Другая часть динамической библиотеки в любом случае загружается в память каждого процесса, который использует эту библиотеку.) Если системная программа BlobContainer
не включена в решение, то отдельные экземпляры динамической библиотеки загружаются в память процессов, использующих эту библиотеку. Динамическая библиотека, от которой зависит нескольких других динамических библиотек, загружается в разделяемую память или память процесса в единственном экземпляре.
Если задать через переменную окружения 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. Динамическая библиотека, загруженная в память процесса вызовом функции dlopen()
, выгружается вызовом функции dlclose()
. Динамическая библиотека, скомпонованная с программой, не может быть выгружена из памяти до завершения процесса, в контексте которого эта программа исполняется. Динамическая библиотека, скомпонованная с другими динамическими библиотеками, выгружается из памяти после выгрузки всех библиотек, которые зависят от нее, либо после завершения процесса.