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