Динамическая библиотека ссылок в C - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть несколько вопросов о библиотеках динамической компоновки в C.

Q1. enter image description here

Мои учебники используют картинку, чтобы проиллюстрировать, как работает DLL, и кажется, что некоторая информация таблицы перемещений и таблиц символов libvector.so и libc.so копируется (стрелка прикреплена к их стороне), но всякий раз, когда ассемблер встречает ссылку на объект, конечное местоположение которого неизвестно, он генерирует перемещение запись, которая сообщает компоновщику, как изменить ссылку, когда он объединяет объектный файл в исполняемый файл. Для libc.so все известно (в нем есть все определения), поэтому не должно быть записи о перемещении для libc.so, не так ли

Q2. Мой учебник говорит, что:

«Отдельная копия раздела .text общей библиотеки в памяти может использоваться разными запущенными процессами»,

Допустим, у меня есть программа, которая использует printf. Сохраняется ли секция .text в printf в ОЗУ навсегда или она удаляется из ОЗУ после завершения первой программы и загружается в ОЗУ, когда второй процесс снова использует printf? Если это так, не слишком ли неэффективно, что секция .text в printf выселяется и загружается в ОЗУ много раз, поскольку у нас есть несколько процессов, которые могут работать в фоновом режиме?

1 Ответ

0 голосов
/ 08 ноября 2018

Q1: Диаграмма, которую вы предоставили, мне кажется правильной. Это main2, которое строится; информация о перемещении и таблица символов libvector.so и libc.so копируются, чтобы их мог использовать конечный исполняемый файл. С точки зрения main2, добавляются функции, константы и т. Д. Из libc и libvector, поэтому я согласен с вашим учебником в том, что информация о перемещении и таблица символов libvector.so и libc.so копируются .

Q2: Вы представляете только две крайности: «оставаться в ОЗУ навсегда» или «выселены из ОЗУ после завершения первой программы». Почти наверняка разделяемые части библиотек останутся в оперативной памяти, если какой-то недавно запущенный процесс использовал их. Типичная стратегия, которую ОС будет использовать, - это алгоритм LRU для удаления «неиспользуемых» вещей из ОЗУ, но только когда она хочет загрузить в ОЗУ больше, чем есть место. Таким образом, на слегка используемой машине почти все может зависать в ОЗУ в течение достаточно долгого времени; но на очень сильно перегруженной машине ОС будет постоянно отбрасывать из оперативной памяти вещи, которые ей понадобятся очень скоро. Но даже тогда некоторые вещи используются так часто, что они вряд ли когда-либо достигнут порога LRU, поэтому у вас могут быть определенные вещи в ОЗУ в течение длительного времени, даже если большинство вещей выселяется.

Продолжение Q1: В ответ на ваш вопрос в комментарии: правильно: в main2.c нет ничего, чтобы определить функции, найденные в libc. Это , потому что из этого, что компоновщик должен скопировать в информацию таблицы перемещений и символов для printf() из libc.so, чтобы при выполнении main2 также загружался libc.so.

Более подробно:

printf() может быть , называемым от main2.c, но printf() является объявленным в stdio.h и определенным , например. printf.c [1] и скомпилированы в libc.so; main2.c может быть скомпилировано , потому что компилятор может видеть подпись для printf()stdio.h), но для сборки main2 (исполняемый файл) необходим код, уже скомпилированный в libc.so быть связанным с main2.o (промежуточный объектный файл). ld делает это путем копирования ссылок, которые приводят к динамической загрузке libc.so при выполнении main2. [2] * * одна тысяча пятьдесят восемь

[1] Компиляторы будут отличаться в зависимости от того, как определены стандартные функции библиотеки; gcc имеет файл printf.c, который определяет printf() (и это на самом деле пропуск vfprintf()); другие компиляторы могут сделать это по-другому - но суть библиотек в том, что вам никогда не нужно смотреть на определение из printf() и другие библиотечные функции; вам нужно только объявление из соответствующего файла .h, чтобы узнать, как вызвать в вашем собственном файле .c.

[2] Или, если вы создаете статически связанный исполняемый файл, код - не просто таблица символов - копируется из файла библиотеки в создаваемый исполняемый файл и этот исполняемый файл может быть запущен даже на машине без файлов .so. То, будет ли динамическое связывание или статическое связывание лучше для создания данного исполняемого файла, зависит от нескольких факторов.

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