Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
osnovy_vt / мультизадачность.ppt
Скачиваний:
59
Добавлен:
21.03.2016
Размер:
237.57 Кб
Скачать

BOOL WINAPI DllEntryPoint(

HINSTANCE hinstDLL,

// идентификатор модуля библиотеки DLL

DWORD fdwReason,

// причина вызова функции

LPVOID lpvReserved

// резерв );

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

-DLL_PROCESS_ATTACH – библиотека загружена в результате запуска процесса, требующего библиотеку, или в результате вызова функции LoadLibrary;

-DLL_THREAD_ATTACH – процесс, использующий библиотеку создал новый

поток;

DLL_THREAD_DETACH – завершен один из потоков процесса, использующего библиотеку;

-DLL_PROCESS_DETACH – библиотека будет выгружена в результате завершения процесса, требующего библиотеку, или в результате вызова функции FreeLibrary. Функция DLLEntryPoint может отменить загрузку библиотеки, если вернет значение FALSE. Для успешной инициализации библиотеки функция должна возвращать значение TRUE.

Для того, чтобы функции DLL-библиотеки были доступны использующим их приложениям, эти функции необходимо сделать экспортируемыми. Самый простой способ экспортировать функции – описать их соответствующим образом в файле определения модуля (*.def) DLL-библиотеки. Ниже приведен пример подобного файла.

LIBRARY mydll

DESCRIPTION “ Dynamic-Link Library” EXPORTS

Func_A @1

Func_B @2

Func_C @3

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

В комплект поставки системы программирования BorlandC++ 5.01 входит утилита IMPDEF, позволяющая сгенерировать по готовому загрузочному модулю DLL-библиотеки соответствующий ему файл определения модуля. При этом все функции, входящие в библиотеку, объявляются экспортируемыми. Естественно, этот файл можно отредактировать, оставив экспортируемыми только некоторые функции, а затем перекомпилировать проект с новым файлом определения модуля. Ниже приведен формат строки запуска этой утилиты. IMPDEF DestName.DEF SourceName.DLL

Для того, чтобы приложение могло вызывать функции DLL-библиотеки, их необходимо описать как импортируемые. Обычно это достигается путем включения в состав компилируемого проекта приложения библиотеки импорта (файл *.lib). Предварительно необходимо на основе DLL-библиотеки создать библиотеку импорта. Для этого предназначена входящая в комплект поставки системы программирования Borland C++ 5.01 утилита IMPLIB. Ниже приведен формат строки запуска этой утилиты.

IMPLIB [options] LibName.LIB SourceName.DEF | SourceName.DLL

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

API WIN32 поддерживает также динамический импорт функций из DLL-библиотек непосредственно в процессе выполнения приложения. Это может потребоваться в том случае, когда в зависимости от логики работы приложения следует импортировать те или иные функции библиотеки. Загрузить любую DLL-библиотеку в память можно при помощи функции LoadLibrary. Функция GetProcAddress позволяет получить указатель на любую экспортируемую функцию библиотеки. Функция FreeLibrary выгружает библиотеку из памяти. Подробную информацию об этих функциях можно получить в справочной документации или в электронном справочнике WIN32 Programmer’s Reference.

Виртуальная память

В Windows, как и в любых других мультизадачных ОС, процессы не имеют доступа к физической оперативной памяти. Каждому процессу выделяется набор виртуальных адресов, называемый виртуальным адресным пространством процесса или просто виртуальной памятью. Каждому процессу WIN32 предоставляется собственное виртуальное адресное пространство в диапазоне виртуальных адресов 4М – 2Г. Все процессы WIN32 загружаются по одному и тому же виртуальному адресу 4М и содержимое виртуальной памяти по некоторому виртуальному адресу свое для каждого процесса. ОС гарантирует, что никакой процесс не имеет физической возможности получить доступ к собственному виртуальному адресному пространству другого процесса.

Процессы WIN32 используют плоскую несегментированную модель памяти FLAT. Для доступа к любой ячейке виртуального адресного пространства в этой модели используется 32-разрядное смещение, деление адресного пространства на сегменты отсутствует. ОС делит виртуальное адресное пространство каждого процесса на страницы фиксированного размера в 4К Физическое адресное пространство оперативной памяти система также делит на страницы размером 4К. При запуске процесса система сначала пытается разместить необходимый код и данные в оперативной памяти. Когда страниц оперативной памяти не хватает, включается механизм подкачки страниц. Этот механизм также включается при необходимости замены страниц, принадлежащих неактивному процессу на страницы активного процесса. Для хранения неиспользуемых в текущий момент страниц используется страничный файл подкачки, размещаемый во внешней памяти (на диске). Верхний предел собственного виртуального адресного пространства каждого процесса может иметь максимальное значение 2Г, но его реальное значение определяется физическими ресурсами вычислительной системы.

Любая страница виртуального адресного пространства процесса может находиться в одном из трех состояний: свободная (free), зарезервированная (reserved) или выделенная для использования (commited) страница. ОС требует от процесса сначала зарезервировать необходимое ему виртуальное адресное пространство, а затем выделить все это пространство или его часть для использования. При этом рекомендуется вначале зарезервировать столько памяти, сколько максимально потребуется процессу, а затем выделять для использования из зарезервированной виртуальной памяти участки, необходимые для выполнения текущих операций. Кроме того, каждой странице виртуального адресного пространства присваивается один из следующих атрибутов защиты: PAGE_READWRITE (чтение и запись), PAGE_READONLY (только чтение), PAGE_EXECUTE(только исполнение), PAGE_EXECUTE_READ (чтение и исполнение), PAGE_EXECUTE_READWRITE (чтение, запись и исполнение), PAGE_NOACCES (запрещен любой доступ). В Windows 95 используются только атрибуты PAGE_READWRITE, PAGE_READONLY и PAGE_NOACCES.

Резервирование и выделение для использования виртуальной памяти выполняется при помощи функции VirtualAlloc:

LPVOID VirtualAlloc(

LPVOID lpvAddress, // адрес резервируемого (выделяемого) участка DWORD cbSize, //размер резервируемого (выделяемого) участка в байтах DWORD fdwAllocationType, // тип выделения

DWORD fdwProtect // атрибут защиты для страниц участка );

ретий параметр функции должен иметь значение MEM_RESERVEдля резервирования участка виртуальной памяти, значение MEM_COMMIT для выделения участка в непосредственное использование и MEM_RESERVE| MEM_TOP_DOWN для резервирования участка в области

старших адресов (в этом случае первый параметр указывается как NULL). Функция возвращает

адрес выделенного участка, кратный 4К, или NULL при ошибке.

После использования необходимо освободить полученную ранее виртуальную память при помощи функции VirtualFree:

BOOL VirtualFree(

LPVOID lpvAddress, // адрес освобождаемого участка DWORD cbSize, // размер участка в байтах

DWORD fdwFreeType // тип операции );

Третий параметр функции может принимать значение MEM_DECOMMIT (страницы помечаются как reserved) или MEM_RELEASE (страницы помечаются как free). Функция возвращает TRUE при успешном освобождении страниц и FALSEпри ошибке.

В состав API WIN32 входят также функции VirtualLock и VirtualUnLock, позволяющие соответственно зафиксировать страницы в оперативной памяти (запретить их перекачку на диск) и расфиксировать их. Функция VirtualProtect позволяет изменить атрибуты защиты страниц уже выделенного блока. Подробную информацию об этих функциях можно получить в справочной документации или в электронном справочнике WIN32 Programmer’s Reference.

В виртуальном адресном пространстве каждого процесса ОС резервирует участок памяти, предназначенный для использования в качестве динамического пула или кучи (heap). Стандартно под кучу резервируется блок памяти размером в 1М, из которого 4К выделены для непосредственного использования. Эти значения могут быть изменены через опции компилятора или с помощью файла определения модуля приложения (*.def). Функция API GetProcessHeap возвращает идентификатор стандартной кучи, который затем может быть использован в качестве одного из параметров функций HeapAlloc, HeapReAlloc, HeapFree, которые соответственно выделяют для использования блок памяти из кучи, изменяют его размер и освобождают блок. Если процессу недостаточно стандартной кучи, он может зарезервировать в собственном виртуальном адресном пространстве область для новой кучи при помощи функции HeapCreate. Созданная куча может быть уничтожена при помощи функции HeapDestroy. Подробную информацию об этих функциях можно получить в справочной документации или в электронном справочнике WIN32 Programmer’s Reference.

Внешняя память

Windows NT поддерживает как собственную файловую систему NTFS, ориентированную на выполнение стандартных файловых операций в мультизадачной среде и имеющую встроенные средства обеспечения безопасности и разграничения доступа, так и файловые системы HPFS OS/2 и FAT MS DOS. Windows 95 использует файловую систему VFAT, базирующуюся на FAT MS DOS, но поддерживающую длинные имена файлов. Однако, API WIN32 использует для выполнения файловых операций универсальные функции, независимо от типа используемой файловой системы.

Для создания и открытия файла используется функция CreateFile: HANDLE CreateFile(

LPCTSTR lpFileName, // указатель на строку с именем файла DWORD dwDesiredAccess, // режим доступа

DWORD dwShareMode, // режим разделения LPSECURITY_ATTRIBUTES lpSecurityAttributes, // указатель на атрибуты

 

 

// безопасности или NULL

DWORD

dwCreationDistribution, // флаги создания

DWORD

dwFlagsAndAttributes,

// атрибуты файла

HANDLE hTemplateFile // идентификатор файла, атрибуты которого //копируются для нового файла или NULL );

Параметр “Режим доступа” может быть равен нулю (доступ запрещен), GENERIC_READ (доступ на чтение), GENERIC_WRITE (доступ на запись) или GENERIC_READ| GENERIC_WRITE (доступ на чтение и запись). Параметр “Режим разделения” может быть равен нулю (совместное использование файла запрещено), FILE_SHARE_READ(другие процессы могут открывать файл на чтение), FILE_SHARE_WRITE(другие процессы могут открывать файл на запись) или FILE_SHARE_READ| FILE_SHARE_WRITE. Через третий параметр функции передается указатель на структуру SECURITY_ATTRIBUTES или NULL (в этом случае атрибуты безопасности объекта ядра файл определяются системой). Флаги создания определяют действия, выполняемые функцией: CREATE_NEW (создать новый файл), CREATE_ALWAYS (если создаваемый файл уже существует, он перезаписывается), OPEN_EXISTING (открывается существующий файл), OPEN_ALWAYS(если открываемый файл не существет, он будет создан и открыт). Параметр “Атрибуты файла” может принимать значения FILE_ATTRIBUTE_HIDDEN (скрытый файл), FILE_ATTRIBUTE_SYSTEM (системный файл), FILE_ATTRIBUTE_READONLY (файл только для чтения), FILE_ATTRI- BUTE_NORMAL (у файла не установлены вышеперечисленные атрибуты), FILE_ATTRIBU- TE_ARCHIVE (файл был модифицирован), FILE_ATTRIBUTE_COMPRESSED (файл динамически сжимается при записи и восстанавливается при чтении). Атрибуты файла могут использоваться совместно с флагами FILE_FLAG_* и SECURITY_*. Информацию об этих флагах можно найти в описании функции CreateFile в справочной документации или в электронном справочнике WIN32 Programmer’s Reference. Заметим, что использование тех или иных значений параметра “Атрибуты файла” зависит также от установленной файловой системы. Функция CreateFile создает и инициализирует объект ядра файл и возвращает его идентификатор типа HANDLE. В случае ошибки возвращается значение INVA- LID_HANDLE_VALUE. Как обычно, более подробную информацию об ошибке можно получить при помощи функции GetLastError.

Внешняя память

Для чтения информации из файла используется функция ReadFile, а для записи – функция WriteFile. Позиционирование записей в файле выполняется функцией SetFilePointer. При совместном использовании файла несколькими процессами важную роль играют функции LockFile и UnlockFile. Функция LockFile блокирует заданный участок файла, предотвращая доступ к нему других процессов. Функция UnLockFile снимает указанное ограничение для заданного участка файла. Как и другие объекты ядра, объект ядра файл закрывается при помощи функции CloseHandle. Подробную информацию об этих функциях можно получить в справочной документации или в электронном справочнике WIN32 Programmer’s Reference.