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
. То, будет ли динамическое связывание или статическое связывание лучше для создания данного исполняемого файла, зависит от нескольких факторов.