Разница между динамическим связыванием во время загрузки и динамическим связыванием во время выполнения - PullRequest
20 голосов
/ 13 января 2010

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

Ответы [ 4 ]

18 голосов
/ 13 января 2010

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

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

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

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

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

Еще один сценарий, в котором полезно связывание во время выполнения, - для отладки библиотек или выбора из нескольких совместимых с ABI / API библиотек во время выполнения. У меня часто есть библиотека, скажем, «foo» и одна, называемая «foo_unstable», и у меня есть тестовое приложение, которое переключается между двумя и выполняет некоторое тестирование.

В 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) во время загрузки. Возможно, библиотека уже находится в памяти.

14 голосов
/ 13 января 2010

Эйден Белл рассмотрел основы, но я добавлю:

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

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

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

11 голосов
/ 07 декабря 2014

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

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

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

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

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

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

0 голосов
/ 24 февраля 2018

В динамическом линковании во время загрузки исполняемый файл связан с библиотекой DLL, тогда как в динамическом линковании во время выполнения ни один исполняемый файл не был связан ни с одной DLL.

Динамическое связывание во время выполнения предпочтительно, когда важна производительность запуска приложения

...