Приложения, работающие в ОС Windows состоят из исполняемых файлов и динамических библиотек (Dynamic Link Library, DLL) [4].
Динамические библиотеки представляют собой исполняемые модули, содержащие функции и данные, которые могут быть использованы другими модулями (приложениями или динамическими библиотеками). С использованием динамических библиотек создаются приложения на основе модульного принципа, вследствие чего эти приложения могут быстрее загружаться и проще обновляться. Кроме того, если некоторые приложения используют одну и ту же динамическую библиотеку, то эта DLL загружается в ОП только один раз и доступ к ней разрешается всем заинтересованным в ее использовании приложениям.
В динамических библиотеках можно определить 2 типа функций: внешние (экспортируемые) и внутренние. Экспортируемые функции могут вызываться как из DLL в которой они описаны, так и из других модулей. Внутренние функции могут использоваться только в том модуле, в котором они описаны.
Хотя динамические библиотеки могут экспортировать данные, в основном данные, описанные в DLL используются функциями, которые описаны в этой же самой DLL. Однако ничто не запрещает другим модулям считывать или записывать данные, описанные в какой - либо динамической библиотеке.
|
|
Набор API-функций, с помощью которых пользовательское приложение взаимодействует с операционной системой, реализован как набор динамических библиотек, поэтому все приложения Windows используют динамические библиотеки.
Динамическое связывание позволяет включать в модули только информацию об экспортируемой в момент загрузки или во время выполнения программы функции DLL. Существует 2 метода вызова функции из DLL.
1. Динамическое связывание во время загрузки (Load-Time Dynamic Linking). В этом случае модуль осуществляет явный вызов экспортируемой функции так, будто она является его локальной функцией. Этот способ требует наличия библиотеки импорта, связанной с DLL содержащей экспортируемые функции, которая обеспечивает ОС информацией, необходимой для загрузки этой DLL и расположением экспортируемых функций внутри DLL.
2. Динамическое связывание во время выполнения программы (Run-Time Dynamic Linking). В этом случае, вызывающее приложение должно использовать специальные API-функции для загрузки DLL, выгрузки DLL и получения адреса экспортируемой функции. Самостоятельное получение адреса экспортируемой функции приводит к тому, что нет необходимости создавать библиотеку импорта.
Каждый процесс, который загружает DLL, отображает ее на свое собственное виртуальное адресное пространство, после чего он может использовать экспортируемые DLL функции.
|
|
Для каждой загруженной DLL ОС создает счетчик обращений. Когда процесс загружает DLL, счетчик обращений увеличивается на 1, когда процесс завершается или когда счетчик обращений становится равным 0 (только для динамического связывания во время выполнения программы) - динамическая библиотека выгружается из виртуального адресного пространства процесса.
Как и другая функция, экспортируемая DLL функция выполняется в контексте того потока, который ее вызвал.
Как уже говорилось, динамические библиотеки представляют собой исполняемые модули, содержащие функции и данные, т.е. фактически - динамические библиотеки не отличаются от обычных программ. Разница заключается лишь в том, что функции, определенные в динамических библиотеках могут вызываться другими программными модулями. Многие среды разработки предоставляют шаблон для создания динамической библиотеки.
Файлы с исходным кодом DLL содержат экспортируемые функции и данные, внутренние функции и данные, и дополнительно процедуру входа DLL. Процедура входа может использоваться для инициализации переменных, очистки необходимой для работы области памяти и т.п.
Для выделения экспортируемых функций, в тексте программы DLL за процедурой, вызываемой из другого модуля, необходимо указать ключевое слово EXPORT (если предполагается транслировать этот модуль с помощью пакета MASM) или объявить эту процедуру как PUBLIC (если предполагается транслировать этот модуль с помощью пакета TASM). Если же используется какая-либо среда разработки, то как правило, создание DLL осуществляется на основе шаблона.
Использование динамически связываемых во время загрузки DLL можно наблюдать в приложении А на примере API-функций.
Для использования динамически связываемых во время выполнения DLL используются следующие API-функции:
LoadLibrary - для загрузки DLL в виртуальное пространство вызывающего процесса и получения описателя (дескриптора) данной библиотеки;
GetProcAddress - для получения адреса процедуры, находящейся в динамической библотеке.
После того как работа динамической библиотеки завершена, её можно выгрузить (если конечно больше ни один из модулей эту DLL не использует), вызвав функцию FreeLibrary.