Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпоры ОС1.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.61 Mб
Скачать

37 . Динамически загружаемые библиотеки (dll). Связывание во время загрузки библиотеки.

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

RVA – relative virtual address – формализация данных в файле.

Просмотреть содержимое таблиц экспорта и импорта можно с помощью утилиты dumpbin.exe из состава пакета MS Visual Studio (консольная программа).

Около 30% функций Win32API лежит в kernel32.dll. Чтобы посмотреть ее табл. экспорта:

dumpbin.exe kernel32.dll \exports>kernel32.exports

Чтобы посмотреть ее табл. импорта:

dumpbin.exe kernel32.dll \imports>kernel32.imports

kernel32.dll экспортирует функции Win32API, а импортирует функции из ntdll.dll, т.е. Native API.

Другой способ исследования взаимосвязей между библиотеками – использование еще одной программы Dependency Walker (depends.exe) из состава MS Visual Studio (программа с GUI).

После того, как все библиотеки были загружены по табл. импорта от программы и по табл. импорта от библиотек, управление передается процессу – статическая загрузка. Динамическая загрузка в процессе работы программы может подгружать библиотеки.

Создание DLL - динамически загружаемой библиотеки

Для создания DLL необходимо при создании проекта в среде MS Visual Studio указать тип проекта не exe-файл, а dll. У DLL отсутствует функция WinMain. Вместо нее используется DllMain.

BOOL WINAPI DllMain( HINSTANCE hInstDll, // HINSTANCE можно заменить на HMODULE DWORD fdwReason, LPVOID lpvReserved);

  1. Адрес точки загрузки модуля в память. Для программ он равен 0x400000, для библиотек 0x10000000 (по умолчанию). Если 2 библиотеки загрузить по этому адресу, то загрузчик сам сдвинет 2-ю библиотеку.

  2. Причина вызова функции. 3. Зависит от 2.

Функция DllMain вызывается в 4-х случаях, при этом fdwReason будет принимать следующие значения:

  • DLL_PROCESS_ATTACH – при загрузке dll в адресное пространство процесса;

  • DLL_THREAD_ATTACH – при создании новой нити;

  • DLL_THREAD_DETACH – при уничтожении нити;

  • DLL_PROCESS_DETACH – при выгрузке dll из адресного пространства процесса.

  • Параметр lpvReserved имеет смысл в 2-х случаях:

  • при DLL_PROCESS_ATTACH этот параметр равен 0 для динамической загрузки и не равен 0 для статической загрузки;

  • при DLL_PROCESS_DETACH этот параметр равен 0 для динамической выгрузки и не равен 0 для выгрузки в связи с завершением процесса.

Т.о., библиотека может настраиваться для процесса и для нити как ей хочется. Любую ф-цию, переменную, класс библиотеки можно сделать экспортируемыми, т.е. подключаемыми извне с помощью табл. экспорта. Чтобы адрес ресурса был помещен в табл. экспорта необходимо непосредственно перед определением ресурса написать ключевые слова:

__declspec (dllexport) int; // для переменной

__declspec (dllexport) void func();// для функции

class __declspec (dllexport) MyClass; // для класса

При статическом связывании в программе, которая будет пользоваться ресурсами библиотеки необходимо написать то же самое, только не export, а import. Следовательно, можно сделать следующее. Написать в заголовочном файле:

#ifdef _DLL #define DLLLINK __declspec (dllexport)

#else #define DLLLINK __declspec (dllimport)

А в программе:

DLLLINK int; DLLLINK void func(); class DLLLINK MyClass;

Т.е. в программе можно будет импортировать, а в dll экспортировать.

При сборке exe-файла необходимо в опциях компоновщика вписать имя файла этой библиотеки, только с расширением *.lib. (в additional dependencies).

-prog.exe -mydll.dll -mydll.lib – в этом файле лежат адреса, которые нужно прописать в таблице импорта exe-файла.

Динамическое связывание

HMODULE LoadLbrary(

LPCTSTR sz Name);

Эта функция загружает библиотеку. Ошибка, если библиотека не найдена. Адрес экспортируемого ресурса L задается функцией:

VOID * GetProcAddress (

HMODULE hDLL,

LPCSTR szResourceName);

GetProcAddress не может иметь Unicode, а только ASCII.

В таблице экспорта ресурс может находиться как именованный, так и не именованный. Эта функция загружает и такие и такие.

LPCSTR – не указатель, а номер ресурса (0-65535).

Компилятор при создании динамически загружаемой библиотеки формирует имена экспортируемых ресурсов таким образом, чтобы в имени содержалась вся инф-ция о параметрах функции и о параметре возврата.

Void *Func()

“& Func@@ YAXXZ”

Компилим DLL, смотрим, что она экспортирует с помощью утилиты DumpBin.exe . смотрим, во что преобразовалось наше имя и подставляем его в функцию GetProcAddress.

Исп-ем *.def – файл. В них лежат имена экспортируемых ресурсов.

Func_Func.

После работы с библиотекой ее можно выгрузить. Это делает функция freelibraty:

BOOL FreeLibrary (

HMODULE hDLL);