Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Роджерсон Д. - Основы COM - 2000.pdf
Скачиваний:
412
Добавлен:
13.08.2013
Размер:
2.4 Mб
Скачать

10 глава

Серверы в EXE

В последний раз я был в Берлине еще до падения стены. Когда, покидая американский сектор у пропускного поста «Чекпойнт Чарли», я въезжал в Восточный Берлин, не возникало сомнений, что здесь проходит граница. Колючая проволока, автоматчики и минные поля делали ее весьма отчетливой. Но и за оборонительной линией отличия были очевидны: с восточной стороны от стены двухлитровые малолитражки изрыгали густой дым, а возле магазинов стояли длинные очереди.

Изменения ждут нас при всяком переходе границы, неважно, сколь мало отличается одна сторона от другой. Эта глава посвящена пересечению границ — главным образом, границ между разными процессами. Мы рассмотрим также пересечение границ между машинами.

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

Если компонент и клиент находятся в разных EXE, они будут расположены и в отдельных процессах, поскольку для каждого EXE-модуля создается свой процесс. При передаче информации между такими компонентом и клиентом необходимо пересечь границу между процессами. По счастью, при этом нет нужды изменять код компонента, хотя некоторые изменения в класс CFactory, представленный в предыдущей главе, внести все же придется. Однако, прежде чем перейти к реализации, следует рассмотреть проблемы и решения, связанные с обращением к интерфейсам СОМ через границы процессов.

Разные процессы

Каждый модуль EXE исполняется в отдельном процессе. У каждого процесса есть свое адресное пространство. Логический адрес 0x0000ABBA в двух разных процессах ссылается на два разных места в физической памяти. Если один процесс передаст этот адрес другому, второй будет работать не с тем участком памяти, который предполагался первым процессом (рис. 10-1).

В то время как каждому EXE-модулю соответствует свой процесс, DLL проецируется в процесс того EXE, с которым они скомпонованы. По этой причине DLL называют серверами внутри процесса (in process), а EXE — серверами вне процесса (out of process). Иногда EXE также называют локальными серверами, чтобы отличить их от другого вида серверов вне процесса — удаленных серверов. Удаленный сервер — это сервер вне процесса, работающий на другой машине.

 

 

 

Адресное пространство

Физическая память

 

Процесс 1

 

 

 

процесса 1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

pFoo

 

 

 

 

0x0000ABBA

 

 

 

 

0x00001234

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Адресное пространство

 

 

 

 

Процесс 2

 

 

 

процесса 2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

pFoo

 

 

 

 

0x0000ABBA

 

 

 

 

0x0BAD0ADD

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рис. 10-1 Один и тот же адрес в двух разных процессах ссылается на два разных участка физической памяти

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

160

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

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

!" Процесс должен иметь возможность передавать другому процессу данные.

!" Клиент не должен беспокоиться о том, является ли компонент сервером внутри или вне процесса.

Локальный вызов процедуры

Есть много методов межпроцессной коммуникации, включая DDE, именованные каналы и разделяемую память. Однако СОМ использует локальный вызов процедуры (local procedure call, LPC). LPC — это средство связи между разными процессами на одной и той же машине. LPC представляет собой специализированное средство связи между разными процессами в пределах одной машины, построенное на основе удаленного вызова процедуры (remote procedure call, RPC) (см. рис. 10-2).

Стандарт RPC определен OSF (Open Software Foundation) в спецификации DCE (Distributed Computing Environment) RPC. RPC обеспечивает коммуникацию между процессами на разных машинах с помощью разнообразных сетевых протоколов. Распределенная модель СОМ (DCOM), которую мы будем рассматривать далее в этой главе, использует RPC для связи по сети.

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

EXE

Клиент

Граница процесса

EXE

Компонент

Локальный вызов процедуры

Рис. 10-2 Клиент в EXE использует механизм Win32 LPC для вызова функций компонента, реализованного в другом EXE

Маршалинг

Вызвать функцию EXE — это только полдела. Нам по-прежнему необходимо передать параметры функции из адресного пространства клиента в адресное пространство компонента. Этот процесс называется маршалингом (marshaling). В соответствии с моим словарем, глагол marshal значит «располагать, размещать или устанавливать в определенном порядке». Это слово должно быть в нашем ближайшем диктанте.

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

Механизм LPC способен скопировать данные из одного процесса в другой. Но для выборки параметров и посылки их в другой процесс ему требуется больше информации, чем содержится в заголовочном файле С++. Например, указатели на структуры следует обрабатывать иначе, чем целые числа. Маршалинг указателя включает в себя копирование в другой процесс структуры, на которую указатель ссылается. Однако, если указатель — это указатель на интерфейс, то область памяти, на которую он ссылается, копироваться не должна. Как видите, для выполнения маршалинга нужно сделать больше, чем просто вызвать memcpy.

Для маршалинга компонента предназначен интерфейс IMarshal. В процессе создания компонента СОМ запрашивает у него этот интерфейс. Затем СОМ вызывает функции-члены этого интерфейса для маршалинга и демаршалинга параметров до и после вызова функций. Библиотека СОМ реализует стандартную версию IMarshal, которая работает для большинства интерфейсов. Основной причиной создания собственной версии

Соседние файлы в предмете Программирование на C++