Подтвердить что ты не робот

Разница между динамической компоновкой нагрузки и динамической связью во время выполнения

При загрузке программ в память, в чем разница между динамической компоновкой нагрузки и динамической связью во время выполнения?

4b9b3361

Ответ 1

привязка времени загрузки - это когда символы в библиотеке, на которые ссылается исполняемый файл (или другая библиотека), обрабатываются при загрузке исполняемого файла/библиотеки в операционную систему.

Связывание времени выполнения - это когда вы используете API, предоставляемый ОС или через библиотеку для загрузки DLL или DSO, когда вам это нужно, и затем выполняйте разрешение символа.

Я знаю больше о Linux DSOs, чем Windows DLL, но принцип должен быть таким же. Библиотеки .NET могут отличаться.

В linux архитектура плагинов выполняется таким образом. Ваша программа будет использовать связь во время выполнения, чтобы загрузить библиотеку и вызвать некоторые функции. Тогда, возможно, выгрузите его. Он также позволяет загружать сразу несколько библиотек с одинаковыми экспортируемыми символами без столкновения. Я думаю, DLL будут работать одинаково.

В исполняемых файлах есть "пробелы" в их таблицах символов, которые должны заполняться некоторой библиотекой. Эти пробелы обычно заполняются во время загрузки или времени компиляции. Вы можете отменить необходимость "пробелов" в таблице символов, используя привязку времени выполнения.

Другим сценарием, в котором используется компоновка времени выполнения, является использование отладочных библиотек или выбор из нескольких библиотек, совместимых с ABI/API, во время выполнения. У меня часто есть библиотека, скажем "foo" и одна называется "foo_unstable", и у вас есть тестовое приложение, которое переключается между 2 и выполняет некоторые тесты.

В Linux, чтобы узнать, в каких библиотеках исполняемый файл подключается во время загрузки, вы запускаете команду ldd и получаете вывод, например (on/bin/ls):

linux-vdso.so.1 =>  (0x00007fff139ff000)
librt.so.1 => /lib64/librt.so.1 (0x0000003c4f200000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003c4fa00000)
libcap.so.2 => /lib64/libcap.so.2 (0x0000003c53a00000)
libacl.so.1 => /lib64/libacl.so.1 (0x0000003c58e0000

Операционная система будет пытаться загружать библиотеки (файлы .so) во время загрузки. Возможно, у него уже есть библиотека в памяти.

Ответ 2

Айден Белл описал основные принципы, но я добавлю:

Динамическое связывание времени загрузки обычно выполняется путем статической привязки вашего приложения к файлу .lib или .a, который содержит код для автоматического установления ссылок на время выполнения для символов, которые можно найти в файлах .dll или .so в программе запускать. Обычно это используется для фиксированной функциональности (т.е. Библиотеки времени выполнения C и т.д.) И позволяет вашей программе использовать преимущества исправлений ошибок в библиотеках, сохраняя при этом размер исполняемого файла небольшим (за счет включения общего кода в одну библиотеку).

Связывание времени выполнения используется для более динамических функций, таких как загрузка плагинов. Как сказал Айден, вы используете LoadLibrary() или эквивалент для активного присоединения модулей к вашей программе во время выполнения, возможно, путем опроса каталога, содержащего DLL файлы плагинов, загрузки каждого в свою очередь и общения с ним с помощью API-интерфейсов плагинов homegrown. Таким образом, ваша программа может загружать модули, которые даже не существовали, когда ваше приложение было скомпилировано/связано, и, таким образом, оно может расти органично после развертывания.

В принципе оба метода в конечном итоге вызывают API LoadLibrary(), но используют фиксированный набор символов и библиотек в первом случае и более динамический набор в последнем.

Ответ 3

Прошло много времени с тех пор, как был задан вопрос. И ответы Эйдена и Дрю охватывали большую часть сути. Я просто хочу добавить несколько вещей с точки зрения программиста.

Если вы используете динамическое связывание времени загрузки, мы должны ссылаться на файл LIB. А затем в коде мы можем вызвать метод как обычно. (См. Использование динамической привязки времени загрузки для образца кода)

Если вы используете динамическое связывание во время выполнения, вам нужно управлять загрузкой/освобождением DLL и выполнять поиск по функциям самостоятельно. (См. Использование динамической привязки времени выполнения для образца кода)

Для выбора между двумя опциями проверьте Определение способа использования ссылок.

Итак, я думаю, что динамическое связывание нагрузки - это еще один способ сохранить усилия программистов. Но это связано с ценой некоторой расширяемости. Вы можете использовать только DLL, соответствующую файлам LIB, которые вы используете в качестве библиотеки импорта.

В принципе, оба подхода для ссылок используют API LoadLibrary() на платформе Windows.