Компоновка с динамическими библиотеками [3]
Последним из основных способов оповестить динамический компоновщик о местонахождении библиотек является набор соответствующих записей в файле "
/etc/ld.so.conf". Как мы знаем, из коробки компоновщику известно несколько путей, по которым могут лежать библиотеки (lib, /usr/lib).
Для того, чтобы расширить этот список, можно внести набор соответствующих записей в конфиг (ld.so.conf), который используется программой
ldconfig для того, чтобы создать необходимый компоновщику бинарный кэш "
/etc/ld.so.cache" с информацией о всех зависимостях, найденных по заданным путям. Анализируя данный кэш, загрузчику станет понятно, какая библиотека требуется приложению на этапе выполнения.
Почему компоновщик не читает ld.so.conf напрямую? Чтение кэша - более быстрая процедура, относительно анализа файла конфигурации: нужно проверить инклуды, пройтись по файловой системе, открыть каждый файл, считать его содержимое, найти зависимости. С таким подходом потребовалось бы значительное количество дополнительных операций на этапе выполнения для того, чтобы связаться с библиотекой - лишние тормоза и задержки нам ни к чему.
Если посмотреть внутрь ld.so.conf, можно увидеть следующее:
$ cat ld.so.conf
include /etc/ld.so.conf.d/*.conf
/usr/lib/mysql
Это значит, что содержимое всех файлов с сигнатурой
<filename>.conf в каталоге "
/etc/ld.so.conf.d/" будет рассмотрено при формировании итогового кэша:
$ ls /etc/ld.so.conf.d/
libc.conf
$ cat /etc/ld.so.conf.d/libc.conf
/usr/local/lib
Соответственно, для того, чтобы компоновщик смог найти библиотеку, с которой ваше приложение связано, необходимо записать полный путь до директории либо в ld.so.conf, либо в отдельный файл, который следует включить в список поиска через ключевое слово include.
После внесения изменений в конфиг, необходимо обязательно обновить кэш, иначе пути, которые вы прописали, останутся без внимания компоновщика:
$ sudo ldconfig
Подводя черту, можно сказать, что динамические библиотеки, необходимые программе, ищутся в нескольких местах со следующим приоритетом:
1. (только для ELF) Если исполняемый файл содержит запись
DT_RPATH с какими-либо каталогами, то поиск будет выполнен по ним.
2. Если определена переменная среды
LD_LIBRARY_РАТH, то поиск будет выполнен последовательно по каждому каталогу, который в ней указан. Если исполняемый файл устанавливает пользовательский (SUID) или групповой (SGID) идентификатор, то переменная игнорируется. Это делается в целях безопасности, чтобы не дать пользователю обмануть динамический компоновщик, заставив его загрузить вместо требуемой библиотеки ее приватную версию с тем же именем.
3. (только для ELF) Если исполняемый файл содержит запись
DT_RUNPATH с какими-либо каталогами, то они будут использованы во время поиска.
4. Проверяется файл
/etc/ld.so.cache на наличие записи для соответствующей зависимости. Если бинарный файл был связан с опцией компановщика "
-z nodeflib", библиотеки в путях по умолчанию (lib и /usr/lib), будут пропущены.
5. Выполняется поиск по каталогам lib и /usr/lib (именно в таком порядке). Если бианрный файл был связан с опцией компановщика "
-z nodeflib", данный шаг будет пропущен.