Отображение файлов на память
ТЕОРЕТИЧЕСКОЕ ОПИСАНИЕ
Обмен данными между процессами
Операционная система Windows предоставляет пользователю возможность запустить одновременно несколько приложений. Как правило, пользователь именно так и поступает. Однако сама по себе эта достаточно важная особенность Windows не имела бы столь большого значения, если бы не существовали удобные механизмы обмена данными между приложениями.
Студентам предлагается изучить методы обмена данными между процессами и выполнить лабораторную работу по одному из этих методов, по выбору преподавателя.
Механизм DDE
Приложения, использующие технологию динамического обмена данных DDE, выступают как клиенты или серверы (или одновременно как клиенты и серверы). Клиентом и сервером называются процессы (программы или приложения), работающие одновременно на одном или разных компьютерах (объединенных в сеть), и взаимодействующих между собой определенным образом. Клиент посылает серверу запрос на получение данных или выполнение какой-либо работы. Это может быть запрос к серверу базы данных, задание серверу резервного копирования дисков или что-то аналогичное.
Процесс передачи запроса серверу называется транзакцией. Строго говоря, транзакция - это совокупность трех действий: посылка запроса, выполнение запроса, прием ответа.
В процессе инициализации сервер должен выполнить такие действия:
- зарегистрировать себя в библиотеке DDEML;
- зарегистрировать предоставляемый сервис, которым сможет воспользоваться приложение-клиент
Клиент должен сделать следующее:
- зарегистрировать себя в библиотеке DDEML;
- создать канал связи с сервером, указав необходимый сервис
Если приложение собирается использовать DDEML, оно должно зарегистрировать себя в библиотеке DDEML, вызвав специально предназначенную для этого функцию с именем DdeInitialize.
Следующий этап в инициализации сервера DDEML заключается в регистрации предоставляемого им сервиса.
Библиотека DDEML использует трехступенчатую схему адресации данных, передаваемых по каналу связи - сервис (service), раздел (topic) и элемент данных (data item). Приложение задает элементы адреса в виде текстовых строк размером не более 255 байт.
Сервер DDEML может предоставлять сервис одного или нескольких видов. Как правило, один сервер предоставляет только один сервис, причем текстовая строка, идентифицирующая сервис, часто совпадает с именем приложения.
Второй элемент адреса - раздел. В рамках одного сервиса можно определить несколько разделов. Когда клиент DDEML создает канал с сервером, он указывает сервис и раздел. Раздел объединяет группу элементов данных или выполняемых функций. Канал DDEML служит для передачи блоков данных. В рамках одного раздела сервер может обмениваться с клиентом разными блоками данных, каждый из которых идентифицируется при передаче именем элемента данных. В процессе создания канала связи не требуется указывать элементы данных.
Регистрация сервиса выполняется сервером DDEML обычно сразу после вызова функции DdeInitialize и выполняется в два этапа. На первом этапе текстовая строка имени сервиса сохраняется в специальной системной таблице (таблице атомов), для чего вызывается функция DdeCreateStringHandle.
Идентификатор текстовой строки, возвращенный функцией DdeCreateStringHandle и соответствующий регистрируемому сервису, следует передать функции DdeNameService
Перед завершением работы сервер DDEML должен отменить весь зарегистрированный им ранее сервис, вызвав функцию DdeInitialize с параметром afCmd, имеющим значение DNS_UNREGISTER.
Последнее, что нужно сделать перед началом передачи данных по каналу DDEML, - создать канал связи (conversation). Канал связи между клиентом и сервером создается всегда по инициативе клиента. После регистрации в библиотеке DDEML клиент вызывает функцию DdeConnect, создающую канал связи.
Для того чтобы получить данные от сервера, клиент должен послать серверу транзакцию XTYP_REQUEST. Задача посылки серверу транзакции решается с помощью функции DdeClientTransaction
Обратная процедура - передача данных серверу состоит из двух шагов. Вначале надо создать блок глобальной памяти и записать в него передаваемые данные. Для этого следует воспользоваться функцией DdeCreateDataHandle. Затем клиент должен передать серверу транзакцию XTYP_POKE, вызвав для этого функцию DdeClientTransaction.
Отображение файлов на память
Этот способ обладает высоким быстродействием, так как данные передаются между процессами непосредственно через виртуальную память.
Для создания отображения файла на память приложение, прежде всего, должно открыть файл при помощи функции CreateFile. После того как файл открыт, чтобы создать отображение файла, надо вызвать функцию CreateFileMapping. В одном из параметров этой функции нужно передать идентификатор файла, для которого будет выполняться отображение в память, или значение 0xFFFFFFFF. В первом случае функция CreateFileMapping отобразит заданный файл в память. Если же вы создаете отображение только для того чтобы обеспечить передачу данных между процессами, вам не нужно создавать файл на диске компьютера. Указав в качестве идентификатора файла значение 0xFFFFFFFF, вы создадите отображение непосредственно в виртуальной памяти без использования дополнительного файла.
Функция CreateFileMapping в случае успеха возвращает идентификатор объекта-отображения. После этого надо выполнить само отображение, вызвав для этого функцию MapViewOfFile или MapViewOfFileEx. В результате заданный фрагмент отображенного файла будет доступен в адресном пространстве процесса. Водном из параметров функции MapViewOfFile определяется требуемый режим доступа к отображению, то есть режимы доступа для страниц виртуальной памяти, используемых для отображения. В случае успешного выполнения отображения функция MapViewOfFile возвращает адрес отображенной области памяти. При ошибке возвращается значение NULL. Функция MapViewOfFileEx используется, если необходимо выполнить отображение в заранее выделенную область адресного пространства. Эта функция аналогична функции MapViewOfFile за исключением того, что она имеет дополнительный параметр - предполагаемый адрес для выполнения отображения.
Выполнение отображения с использованием функции MapViewOfFileEx используется в тех случаях, когда с помощью файла, отображаемого на память, организуется общая область памяти, доступная нескольким работающим параллельно процессам. При этом вы можете сделать так, что начальный адрес этой области будет одним и тем же для любого процесса, работающего с данным отображением.
Другой способ обмена данными между процессами с использованием отображения файла на память заключается в следующем. Первый процесс создает отображение, указывая для него имя. Второй процесс, который будет выполнять обмен данными с первым процессом, должен открыть это отображение по имени при помощи функции OpenFileMapping. Далее второе приложение выполняет отображение, вызывая функцию MapViewOfFile. Пользуясь значением, полученным от функции MapViewOfFile, второе приложение получает указатель на отображенную область памяти. Физически эта область находится в тех же страницах виртуальной памяти, что и область, созданная первым процессом. Таким образом, два процесса получают указатели на общие страницы памяти.
Следует отметить, что перед завершением своей работы процессы должны отменить отображение файла и освободить идентификатор созданного объекта-отображения с помощью функций UnmapViewOfFile и CloseHandle соответственно.