Когда выполняется динамическое связывание между программой и общей библиотекой? - PullRequest
0 голосов
/ 10 июня 2018

В C, когда выполняется динамическое связывание между программой и общей библиотекой:

  • После загрузки программы в память, но перед выполнением main() программыили

  • После выполнения main() программы, когда будет выполнен первый вызов подпрограммы из библиотеки?Произойдет ли динамическое связывание снова, когда будет выполнен второй или третий или ... вызов подпрограммы из библиотеки?

Я думал первым, пока не прочитал следующую цитату, итеперь я не уверен.

Не уверен, что ОС имеет значение, я использую Linux.

Из концепции операционной системы:

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

Когда заглушка выполняется , она проверяет, находится ли необходимая подпрограмма в памяти.Если это не так, программа загружает подпрограмму в память.В любом случае заглушка заменяет себя адресом подпрограммы и выполняет подпрограмму.Таким образом, в следующий раз, когда конкретный сегмент кода будет достигнут , библиотечная подпрограмма будет выполнена напрямую, без затрат на динамическое связывание.По этой схеме все процессы, использующие языковую библиотеку, выполняют только одну копию кода библиотеки.

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

ОС (и компилятор, и т. Д. ), безусловно, имеют значение: самому языку нечего сказать о динамических библиотеках (и очень мало о ссылках вообще).Даже если мы знаем, что происходит динамическое связывание, строго согласованная программа не может наблюдать какого-либо эффекта от синхронизации среди своих единиц перевода (поскольку нелокальная инициализация не может иметь побочных эффектов ).

ТоСказано, что общие наборы инструментов в Linux поддерживают автоматическую инициализацию при загрузке динамической библиотеки (для реализации C ++, среди прочего).Исполняемые файлы и динамические библиотеки, от которых они зависят (обычно задаются с помощью -l), загружаются и рекурсивно инициализируются , чтобы позволить инициализации в каждом модуле (успешно) использовать функции из его зависимостей.(В некоторых случаях неудачный выбор порядка.) Конечно, dlopen(3) можно использовать для загрузки и инициализации большего количества библиотек позже.

0 голосов
/ 11 июня 2018

Я думал первым, пока не прочитал следующую цитату, и теперь я не уверен.

Это сложно (и зависит именно от того, что вы называете "динамическое связывание").

Ядро Linux загружает a.out в память.Затем он проверяет сегмент PT_INTERP (если есть).

Если этот сегмент отсутствует, двоичный файл статически связан, и ядро ​​передает управление Elf{32,64}Ehdr.e_entry (обычно подпрограмме _start).

Если сегмент PT_INTERP присутствует , ядро ​​загружает его в память и передает управление на , это .e_entry.Именно здесь начинается динамическое связывание .

Динамический загрузчик перемещает себя, а затем ищет в сегменте a.out s PT_DYNAMIC инструкции о том, что еще необходимо.

Например, он обычно находит одну или несколько записей DT_NEEDED - общие библиотеки, с которыми a.out была напрямую связана.Загрузчик загружает любые такие библиотеки, инициализирует их и разрешает любые ссылки data между ними.

IF a.out s PT_DYNAMIC имеет запись DT_FLAGSи если эта запись содержит флаг DF_BIND_NOW, то функция ссылки из a.out также будут разрешены.В противном случае (и при условии, что LD_BIND_NOW не установлен в среде), будет выполняться отложенное разрешение PLT (разрешение функций как часть первого вызова любой данной функции).Подробности здесь .

Когда выполняется заглушка, она проверяет, находится ли необходимая подпрограмма в памяти.Если это не так, программа загружает подпрограмму в память.

Я не знаю, из какой книги вы цитируете, но текущая ОС UNIX не работает таким образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...