Как разделяемые библиотеки экономят память?
Чтобы лучше понять это, сравним разделяемую и архивную библиотеки.
Разделяемая библиотека сборки напоминает архивную библиотеку в трех отношениях. Во-первых, как было сказано выше, оба файла являются архивами. Во-вторых, в объектных модулях библиотеки обычно определяются имена функций и данных, предназначенных для использования многими программами. Имена, определяемые внутри библиотеки и доступные извне, мы будем называть экспортируемыми. Заметим, что в библиотеке могут также содержаться имена, которые в ней используются, но обычно не определяются, и которые мы будем называть импортируемыми. В-третьих, редактор связей просматривает библиотеки в поисках имен, которые он может использовать для разрешения внешних ссылок, после чего создается выполняемый файл.
Примечание
Редактор внешних связей ОС UNIX является средством статического редактирования. Это означает, что все внешние ссылки программы должны быть разрешены к моменту начала ее выполнения. Как с архивной, так и с разделяемой библиотеками редактирование внешних связей является статическим.
Хотя между архивной и разделяемой библиотекой есть сходство, в целом они существенно различны. Главные различия, о которых мы уже кратко рассказывали выше, относятся к способу использования библиотеки для разрешения внешних ссылок.
Рассмотрим работу ОС UNIX с библиотекой каждого из типов в процессе редактирования связей. Работая с архивной библиотекой, редактор связей копирует ее модули, в которых определяются внешние имена редактируемой программы, в секции .text и .data
выполняемого файла. Если же редактор связей работает с разделяемой библиотекой, он ничего не копирует из нее в выполняемый файл. Вместо этого редактор создает специальную секцию .lib, в которой идентифицируются модули разделяемой библиотеки, необходимые для выполнения программы, и разрешает внешние ссылки на эти имена. Когда ОС UNIX выполняет полученный файл, содержимое секции .lib используется для включения соответствующих модулей в адресное пространство процесса.
На рисунке ниже изображена структура выполняемых файлов, полученных с использованием обычной (архивной) и разделяемой библиотек языка C. Исходный текст программы выглядит так:
main () { . . . printf ("Как Вам нравится эта глава?\n"); . . . result = strcmp ("Весьма!", answer); . . . }
Обратите внимание, что версия с разделяемой библиотекой меньше. На следующем рисунке будет изображена структура памяти, занимаемой соответствующими процессами в ходе выполнения.
Рассмотрим теперь, что происходит, когда нескольким выполняемым файлам нужен один и тот же модуль из библиотеки. При использовании архивной библиотеки каждый файл содержит свою собственную копию этого модуля, что приводит к повторению соответствующих фрагментов как на диске, так и в оперативной памяти (во время выполнения). И наоборот, при использовании разделяемой библиотеки, ее модули существуют отдельно от выполняемых файлов, как показано на рисинке ниже. Такое разделение позволяет всем процессам, использующим разделяемую библиотеку, ссылаться на единственную копию ее содержимого.