Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС / Тема_8.ppt
Скачиваний:
137
Добавлен:
11.04.2015
Размер:
1.17 Mб
Скачать

8.1.4. Реализация интерфейса прикладного программирования

Вызов функций стандартных библиотек языка.

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

-языка Паскаль.

Впервом подходе процедуре не известно, сколько параметров находится в стеке. В этом случае освобождение стека от параметров должна осуществлять вызывающая программа после команды вызова процедуры, например, с помощью таких машинных команд, как POP или ADD ESP.n, где n - длина параметров в байтах.

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

ВWindows вызов функций API осуществляется по второй схеме, то есть в стиле языка Pascal. Впрочем, есть и исключения.

Реализация вызова функции DLL-библиотеки может быть

осуществлена двумя способами:

через динамическое связывание с импортом;

через динамическое связывание без импорта.

51

8.1.4. Реализация интерфейса прикладного программирования

Вызов функций стандартных библиотек языка.

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

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

52

8.1.4. Реализация интерфейса прикладного программирования

Динамическое связывание перед выполнением.

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

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

Библиотека импорта описывает состав соответствующей ей DLL- библиотеки, поэтому для каждой DLL-библиотеки существует библиотека с тем же именем, но с расширением .LIB.

Информация о составе DLL-библиотеки необходима компоновщику для установки таблицы косвенных переходов и секции импорта внутри файла .ЕХЕ.

Так, если в программе вызывается функция CreateWindow(), библиотека GDI32.LIB сообщает компоновщику, что данная функция находится в динамически подключаемой библиотеке GDI32.DLL. Поскольку эта информация сохраняется в файле .EXE, Windows может выполнить динамическое связывание программы с библиотекой GDI32.DLL во53время

загрузки программы.

8.1.4. Реализация интерфейса прикладного программирования

Схема создания файла PROGRAM.EXE и используемые при этом библиотеки импорта .LIB.

54

8.1.4. Реализация интерфейса прикладного программирования

Динамическое связывание перед выполнением.

Пример запуска компоновщика для создания программы ргоgram.exe.

С помощью ключа -DEFAULTLIB компоновщику передается информация об используемых DLL-библиотеках.

link.exe –SUBSYSTEM: windows -OUT: program.exe program.obj program.res -DEFAULTLIB: user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib

Библиотеки импорта являются результатом работы компоновщика при создании DLL-библиотек.

Как и объектные библиотеки, библиотеки импорта используются только при разработке программы.

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

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

Если библиотеки в памяти нет, то ее файл ищется в следующем порядке:

в том же каталоге, где находится файл .ЕХЕ программы;

в текущем каталоге;

в системном каталоге Windows;

в каталоге, доступном из переменной PATH в реестре.

55

8.1.4. Реализация интерфейса прикладного программирования

Динамическое связывание перед выполнением.

Врезультате работы компоновщика создается секция импорта idata.

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

56

8.1.4. Реализация интерфейса прикладного программирования

Динамическое связывание перед выполнением.

Кроме секции импорта компоновщик в конце секции .text (здесь находится код программы) создает таблицу косвенных переходов. Эта таблица состоит из команд jmp по одной для каждой функции DLL- библиотеки. Каждая команда jmp ссылается на строку секции idata.

Поскольку команда jmp является командой косвенного перехода, то по указанному в команде адресу, например Адрес1, должен находиться также

адрес.

Однако по адресам Адрес1, Адрес2, ....., АдресN в секции idata первоначально расположены строки с именами функций. Поскольку программа еще не получила управления, это несоответствие можно исправить, что и делает Загрузчик ОС.

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

57

8.1.4. Реализация интерфейса прикладного программирования

Динамическое связывание перед выполнением.

Структура программы после ее связывания с DLL-библиотеками. На этом рисунке вместо строки имя_функции-1 записан адрес этой функции в ОП, обозначенный как адрес_функции-1.

58

8.1.4. Реализация интерфейса прикладного программирования

Динамическое связывание перед выполнением.

Теперь динамическое связывание завершено и программа готова к выполнению, поэтому Загрузчик передает ей управление. В процессе выполнения программы будет осуществляться прямая передача управления функциям DLL-библиотек без вмешательства операционной системы.

Пример

Последовательность действий, выполняемых при вызове функции Create Window() (см. рисунки выше).

Перед выполнением команды call параметры функции записываются в стек. Далее команда call сохраняет адрес возврата в стеке и передает управление по адресу Адрес1. По этому адресу находится команда jmp, расположенная в таблице косвенных переходов. Команда jmp, в свою очередь, извлекает содержимое ячейки по адресу Адрес1, то есть адрес вызываемой функции, и передает управление по этому адресу. Адресом передачи управления является адрес_функции-1, а это не что иное, как адрес функции CreateWindow(). Эта функция извлекает параметры, чистит стек, выполняет свою основную работу и в конце выполняет команду ret. Последняя извлекает из стека адрес возврата, записанный командой call, и передает управление на продолжение

выполнения вызывающей программы.

59

8.1.4. Реализация интерфейса прикладного программирования

Динамическое связывание в процессе выполнения.

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

Предположим, что необходимо выполнить функцию Ellipse3D(), рисующую эллипс в стиле 3D и имеющую формат:

BOLL Ellipse3D (HDC hdc, int x1, int y1, int x2, int y2); Пусть эта функция принадлежит библиотеке Graph3D.dll.

Вызвать функцию Ellipse3D() традиционным способом нельзя, так как в секции импорта idata отсутствует информация о библиотеке, которой принадлежит эта функции.

Введем новый тип:

typedef BOOL (WINAPI * PFNELL3D) (HDC, int, int, int, int);

Определим две переменные:

HMODULE hLibrary; // дескриптор DLL-библиотеки

PFNELL3D pfnEllipse3D(); // адрес (указатель) функции

60

Соседние файлы в папке ОС