Мегаобучалка Главная | О нас | Обратная связь


ЭКЗАМЕНАЦИОННЫЙ БИЛЕТ № 16



2015-12-13 468 Обсуждений (0)
ЭКЗАМЕНАЦИОННЫЙ БИЛЕТ № 16 0.00 из 5.00 0 оценок




1. Ресурсы. Иконки.

2. Наследование описателя объекта.

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

В DLL содержатся все функции Windows API. Три самые важные DLL:

Kernel32.dll (управление памятью, процессами и потоками), User32.dll

(поддержка пользовательского интерфейса, в том числе, функции, связанные с

созданием окон и передачей сообщений) и GDI32.dll (графика и вывод

текста).

В Windows есть другие DLL:

AdvAPI32.dll – содержит функции для защиты объектов, работы с

реестром и регистрации событий

ComDlg32.dll – стандартные диалоговые окна (вроде FileOpen и

FileSave)

ComCtl32.dll – поддерживает стандартные элементы управления

DLL нужно применять для реализации следующих возможностей:

1. Расширение функциональности приложения.

2. Возможность использования разных языков программирования.

3. Более простое управление проектом.

4. Экономия памяти..

5. Разделение ресурсов..

6. Упрощение локализации.

7. Решение проблем, связанных с особенностями различных

платформ..

8. Реализация специфических возможностей.

DLL и адресное пространство процесса.

DLL представляет собой набор модулей исходного кода, в каждом их

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

или другим DLL. Причем в DLL обычно нет кода, предназначенного для

обработки циклов выборки сообщений и создания окон.

Файлы с исходным кодом компилируются и компонуются также, как и при

создании EXE-файла, но при компоновке нужно указать ключ /DLL.

Чтобы приложение (или другая DLL) могла вызывать функции,

содержащиеся в DLL, образ ее файла нужно сначала спроецировать на адресное

пространство вызывающего процесса. Это выполняется за счет неявного

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

При проецировании образа DLL-файла на адресное пространство процесса

система создает также экземпляры глобальных и статических переменных.

Неявное связывание EXE – и DLL – модулей

Неявное связывание (implicit linking) - самый распространенный метод.

Исполняемый модуль (EXE) импортирует функции и переменные из DLL, а

DLL– модули экспортирует их в исполняемый модуль. DLL – также может

импортировать функции и переменные их других DLL.

Создание DLL-модуля

DLL может экспортировать переменные, функции или С++ классы в другие

модули.

При разработке DLL сначала создается заголовочный файл, который

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

При компиляции исходного файла DLL MYLIBAPI определяется как

__declspec (dllexport) до включения заголовочного файла MyLib.h. Такой

модификатор означает, что данная переменная, функция или C++ класс

экспортируется из DLL.

Также следует обратить внимание, что в файле MyLibFile1.cpp перед

экспортируемой переменной или функцией не ставится идентификатор

MYLIBAPI. Он здесь не нужен: проанализировав заголовочный файл,

компилятор запоминает, какие переменные и функции являются

экспортируемыми.

Идентификатор MYLIBAPI включает extern. Модификатор extern не даёт

компилятору искажать имена переменных или функции, и они становятся

доступными исполняемым модулям, написанным на С, С++ или любом другом языке программирования. Этим модификатором можно пользоваться только в коде С++, но ни в коем случае ни в коде на стандартном С.

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

DLL.

А в исходных файлах ЕХЕ-модуля MYLIBAPI определять не надо: включая

заголовочный файл, вы определяете этот идентификатор как –

DLLSPEC(DLLIMPORT), и при помещении исходного кода ЕХЕ-модуля

компилятор поймёт, что переменные и функции импортируются из DLL.

Что такое экспорт

Если перед переменной, прототипом функции или С++ классом указан

модификатор – _deсlspec(dllexport), компилятор Microsoft C/C++ встраивает

в конечный obj-файл дополнительную информацию. Она понадобится при

сборке DLL из OBJ-файлов.

Обнаружив такую информацию, компоновщик создает LIB-файл со списком

идентификаторов, экспортируемых из DLL. Этот LIB-файл нужен при сборке

любого EXE-модуля, ссылающегося на такие идентификаторы. Компоновщик

также вставляет в конечный DLL-файл таблицу экспортируемых

идентификаторов – раздел экспорта, в котором содержится список (в

алфавитном порядке) идентификаторов экспортируемых функций, переменных

и классов. Туда же помещается относительный виртуальный адрес (relative

virtual address, RVA) каждого идентификатора внутри DLL-модуля.

Создание EXE-модуля

Вот пример исходного кода EXE-модуля, который импортирует

идентификаторы, экспортируемые DLL, и ссылается на них внутри в процессе

выполнения.

//Модуль: MyExeFilel.cpp

//Сюда включаются стандартные заголовочные файлы Windows и

библиотеки С

#include <windows.h>

//включаем экспортируемые структуры данных, идентификаторы,

функции и переменные

#include “MyLib\MyLib.h”

….

int WINAPI WinMain(HINSTANCE hinstExe, HINSTANCE,

LPTSTR pszCmdLine, int)

{

int nLeft=10, nRight=25;

TCHAR sz[100];

wsprintf(sz, TEXT(“%d + %d = %d”), nLeft, nRight,

Add(nLeft, nRight));

MessageBox(NULL, sz, TEXT(“Calculation”), MB_OK);

wsprintf(sz, TEXT(“The result from the last Add is: %d”),

g_nResult);

MessageBox(NULL, sz, TEXT(“Last Result”), MB_OK);

return (0);

}

Создавая фалы исходного кода для EXE-модуля, нужно включить в них

заголовочный файл DLL, иначе импортируемые идентификаторы окажутся

неопределенными, и компилятор выдаст массу предупреждений об ошибках.

MYLIBAPI в исходных файлах EXE-модуля до заголовочного файла DLL не

определяется. Поэтому при компиляции приведенного выше кода MYLIBAPI за

счет заголовочного файла MyLib.h будет определен как __declspec(dllimport).

Встречая такой модификатор перед именем переменной, функции или С++

класса, компилятор понимает, что данный идентификатор импортируется из

какого-то DLL –модуля.

Далее компоновщик собирает все OBJ-модули в конечный EXE-модуль. Для

этого он должен знать, в каких DLL содержаться импортируемые

идентификаторы, на которые есть ссылки в коде. Информацию об этом он

получает из передаваемого ему LIB-файла (в котором указан список

идентификаторов, экспортируемых DLL)

Что такое импорт

Импортируя идентификатор, необязательно прибегать к

__declspec(dllimport) – можно использовать стандартное ключевое слово

extern языка С. Но компилятор создаст чуть более эффективный код, если ему будет заранее известно, что идентификатор, на который мы ссылаемся,

импортируется из LIB-файла DLL –модуля.

Разрешая ссылки на импортируемые идентификаторы, компоновщик создаст в конечном EXE-модуле раздел импорта (import section).

В нем перечисляются DLL, необходимые этому модулю, и идентификаторы,

на которые есть ссылки из всех используемых DLL.

Выполнение EXE-модуля

При запуске EXE-файла загрузчик операционной системы создает для его

процесса виртуальное пространство и проецирует на него исполняемый модуль.

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

необходимые DLL на адресное пространство процесса.

Поскольку в разделе импорта указано только имя DLL (без пути), загрузчику

приходится самому искать ее на дисковых устройствах в компьютере

пользователя. Поиск DLL осуществляется в следующей последовательности:

1. Каталог, содержащий EXE-файл

2. Текущий каталог процесса

3. Системный каталог Windows

4. Основной каталог Windows

5. Каталоги, указанные в переменной окружения PATH

Проецируя DLL-модули на адресное пространство, загрузчик проверяет в

каждом из них раздел импорта. Если у DLL есть раздел импорта (что обычно и

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

ведет учет загружаемых DLL, и проецирует их только один раз, даже если

загрузки этих DLL требуют и другие модули.

Найдя и спроецировав на адресное пространство процесса все необходимые

DLL-модули, загрузчик настраивает ссылки на импортируемые

идентификаторы. Для этого вновь просматривает разделы импорта в каждом

модуле, проверяя наличие указанного идентификатора в соответствующей

DLL.

Обнаружив идентификатор, загрузчик отыскивает его RVA и прибавляет к

виртуальному адресу, по которому данная DLL размещена в адресное

пространство процесса, а затем сохраняет полученный адрес в разделе импорта

EXE-модуля. И с этого момента ссылка в коде на импортируемый

идентификатор приводит к выборке его адреса из раздела импорта

вызывающего модуля, открывая таким образом доступ к импортируемой

переменной, функции или функции-члену С++ класса. Как только

динамические связи будут установлены, первичный поток процесса начинает

выполняться.

Загрузчик всех этих DLL и настройка ссылок занимает какое-то время.

Чтобы сократить время загрузки приложения нужно модифицировать базовые

адреса EXE- и DLL-модулей и провести их связывание.

Явная загрузка DLL и связывание идентификаторов

Чтобы поток мог вызвать функцию из DLL-модуля, DLL надо спроецировать

на адресное пространство процесса, которому принадлежит этот поток.

Делается это двумя способами:

1. Код приложения просто ссылается на идентификаторы, содержащиеся в

DLL, и тем самым заставляет загрузчик неявно загружать (и связывать)

нужную DLL при запуске приложения.

2. Явная загрузка и связывание требуемой DLL в период выполнения

приложения. Иначе говоря, поток явно загружает DLL в адресное

пространство процесса, получает виртуальный адрес необходимой DLL-

функции и взывает ее по этому адресу. Изящество этого подхода в том,

что все происходит в уже выполняемом приложении.

 



2015-12-13 468 Обсуждений (0)
ЭКЗАМЕНАЦИОННЫЙ БИЛЕТ № 16 0.00 из 5.00 0 оценок









Обсуждение в статье: ЭКЗАМЕНАЦИОННЫЙ БИЛЕТ № 16

Обсуждений еще не было, будьте первым... ↓↓↓

Отправить сообщение

Популярное:
Организация как механизм и форма жизни коллектива: Организация не сможет достичь поставленных целей без соответствующей внутренней...
Как распознать напряжение: Говоря о мышечном напряжении, мы в первую очередь имеем в виду мускулы, прикрепленные к костям ...
Почему человек чувствует себя несчастным?: Для начала определим, что такое несчастье. Несчастьем мы будем считать психологическое состояние...



©2015-2024 megaobuchalka.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. (468)

Почему 1285321 студент выбрали МегаОбучалку...

Система поиска информации

Мобильная версия сайта

Удобная навигация

Нет шокирующей рекламы



(0.009 сек.)