Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
К_Глава 4_Загрузка программ.doc
Скачиваний:
32
Добавлен:
19.05.2015
Размер:
131.07 Кб
Скачать

3.4 Динамические библиотеки

В WindowsиOS/2 используется именно такой способ загрузки. Исполняемый модуль в этих системах содержит ссылки на другие модули, называемыеDLL(DynamicallyLoadableLibrary, динамически загружаемая библиотека). Фактически, каждый модуль в этих системах обязан содержать хотя бы одну ссылку наDLL, потому что интерфейс к системным вызовам в этих ОС также реализован в видеDLL.

DLLпредставляют собой библиотеки в том смысле, что обычно они собираются из нескольких объектных модулей. Но в отличие от архивных библиотек, изDLLнельзя извлечь отдельный модуль, при присоединении библиотеки к программе она присоединяется и загружается целиком.

Главное достоинство DLLсостоит в том, что модуль (как основной, так и библиотечный), по собственному желанию, может выбирать различные библиотеки, подгружая их после своей собственной загрузки. При этом нет даже строгого ограничения на совместимость этих библиотек по вызовам (две библиотеки совместимы по вызовам, если они имеют одинаковые точки входа с одинаковой семантикой): загрузчик предоставляет возможность просмотреть список глобальных символов, определенных в библиотеке, и получить указатель на каждый символ, обратившись к нему по имени (впрочем, количество и типы параметров или тип переменной, а тем более их семантику, загрузчик не сообщает – эту информацию надо получать из других источников, например из списка зарегистрированных в системе объектовCOM).

Особенно удобна возможность вызывать любую функцию по имени при обращении к внешним модулям из интерпретируемых языков.

При сборке DLLиз нескольких объектных модулей программист должен предоставитьDEF– файл. В этом файле содержится перечисление символов, экспортируемых библиотекой ( в отличие от обычных, “архивных” библиотек, набор этих символов не обязательно равен объединению наборов экспортных символов включенных в библиотеку объектов), а также некоторые другие параметры. Например, можно указать чтоDLLимеет функции инициализации и терминации. Эти функции могут запускаться как при первой загрузке библиотеки, так и при подключении библиотеки очередной программой. Можно также управлять разделением сегмента данныхDLL– применять общий сегмент данных для всех программ, использующих библиотеку, или создавать свою копию для каждой программы.

DLLявляются удобным средством разделения кода и создания отдельно загружаемых программных модулей, но их использование сопряжено с определенной проблемой, которая будет подробнее объясняться далее. Концепция разделяемыхDLLнаиболее естественна в системах, где все задачи используют единое адресное пространство – но при этом ошибка в любой из программ может привести к порче данных или кода другой задачи. Стандартный же способ борьбы с этой проблемой – выделение каждому процессу своего адресного пространства – значительно усложняет разделение кода.

Другая проблема, обусловленная широким использованием разделяемого кода, состоит в слежении за версией этого кода. Действительно, представим себе жизненную ситуацию: в системе одновременно загружены тридцать программ, использующие библиотеку LIBC.DLL. При этом десять из них разрабатывались и тестировались с версией 1.0 этой библиотеки, пять – с версией 1.5 и пятнадцать – с версией 1.5а. Понятно, что рассчитывать на устойчивую работу всех тридцати программ можно только при условии, что все три версии библиотеки полностью совместимы снизу вверх не только по набору вызовов и их параметров, но и по точной семантике каждого из этих вызовов. Последнее требование формулируют какbugforbug(корректно перевести это словосочетание можно так:полная совместимость не только по спецификациям, но и по отклонениям от них).

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