При загрузке программ в память, в чем разница между динамической компоновкой нагрузки и динамической связью во время выполнения?
Разница между динамической компоновкой нагрузки и динамической связью во время выполнения
Ответ 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.