Изменить стиль страницы

Архитектура стандартного маршалинга

Как уже упоминалось ранее в этой главе, СОМ использует протокол ORPC для всех обращений между апартаментами. Это обстоятельство может представлять интерес с точки зрения архитектуры, но некоторые разработчики желают программировать коммуникационный код низкого уровня. Для того чтобы воспользоваться ORPC-коммуникациями, объектам СОМ не требуется делать ничего, кроме реализации IUnknown, для осуществления межапартаментных обращений по протоколу ORPC. По умолчанию при первом вызове CoMarshalInterface для объекта этот объект опрашивается, желает ли он управлять своими собственными межапартаментными связями. Этот вопрос приходит в форме запроса QueryInterface об интерфейсе IMarshal. Большинство объектов не реализуют интерфейс IMarshal и дают отказ на этот запрос со стороны QueryInterface, показывая тем самым, что их вполне удовлетворяет управление всеми связями самой СОМ посредством вызовов ORPC. Те объекты, которые реализуют интерфейс IMarshal, показывают этим, что ORPC им не подходит и что разработчик объекта предпочитает управлять всеми межапартаментными связями посредством специальных заместителей. Когда объект реализует интерфейс IMarshal, то все ссылки на этот объект будут подвергнуты специальному маршалингу. Специальный маршалинг будет обсуждаться позже в данной главе. Если же объект не реализует интерфейс IMarshal, то все ссылки на этот объект будут маршалированы стандартно. Большинство объектов предпочитают использовать стандартный маршалинг, и поэтому ему уделено основное внимание в данном разделе.

Когда CoMarshalInterface впервые определяет, что объект желает использовать стандартный маршалинг, то создается специальный СОМ-объект под названием администратор загушек (stub manager). Это программный модуль, управляющий всеми интерфейсными заглушками активного объекта.

Администратор заглушек действует как идентификационная единица объекта во всей сети и единственным образом идентифицируется Идентификатором Объектов (Object Identifier – OID), который является идентификатором этого объекта во всех апартаментах. Между администраторами заглушек и идентификационными единицами СОМ-объектов имеется взаимно однозначное соответствие. Каждый администратор заглушек ссылается на ровно один СОМ-объект. Каждый СОМ-объект, использующий стандартный маршалинг, будет иметь ровно один администратор заглушек. Администратор заглушек содержит но крайней мере одну неосвобожденную ссылку на объект, которая удерживает ресурсы объекта в памяти. В этом смысле администратор заглушек является еще одним внутрипроцессным клиентом для объекта. Администратор заглушек следит за числом неосвобожденных внешних ссылок и будет существовать до тех пор, пока где-либо в сети останется хотя бы одна неосвобожденная ссылка. Большинство внешних ссылок являются просто заместителями, хотя промежуточные маршалированные объектные ссылки могут удерживать заглушки, чтобы быть уверенными, что в момент создания первого заместителя объект еще существует. Когда неосвобожденные заместители или ссылки уничтожаются, администратор заглушек извещается об этом и декрементирует свой счетчик внешних ссылок. Если уничтожена последняя внешняя ссылка на администратор заглушек, то последний самоуничтожается, освобождая свои неосвобожденные ссылки на действующий объект. Это имитирует эффект наличия на стороне клиента ссылок, поддерживающих объект. Методы явного контроля за временем жизни заглушки будут обсуждаться далее в этой главе.

Администратор заглушек действует лишь как сетевой идентификатор объекта и не понимает, как обрабатывать поступающие ORPC-запросы, предназначенные для объекта[1]. Для того чтобы преобразовать поступающие ORPC-запросы в действительные вызовы методов объекта, администратору заглушек нужен вспомогательный объект, который знает детали сигнатур интерфейсных методов. Этот вспомогательный объект называется интерфейсной заглушкой (interface stub). Он должен правильно демаршалировать параметры [in], которые присутствуют в блоке ORPC-запроса, вызвать метод в действующий объект и затем маршалировать HRESULT и любые параметры [out] в ответный блок ORPC. Интерфейсные заглушки идентифицируются внутри апартамента с помощью Идентификаторов Интерфейсных Указателей (Interface Pointer Identifiers – IPIDs), которые внутри апартамента являются уникальными. Подобно администратору заглушек, каждая интерфейсная заглушка содержит ссылку на объект. Однако поддерживаемый интерфейс будет интерфейсом определенного типа, а не просто IUnknown. На рис. 5.3 показана взаимозависимость между администратором заглушек, интерфейсными заглушками и объектом. Отметим, что некоторые интерфейсные заглушки знают, как декодировать более чем один интерфейсный тип, в то время как другие понимают только один интерфейс.

Сущность технологии СОМ. Библиотека программиста fig5_3.jpg

Когда CoUnmarshalInterface демаршалирует стандартно маршалированную объектную ссылку, фактически эта функция возвращает указатель администратору заместителей (proxy manager). Этот администратор заместителей действует как копия объекта со стороны клиента и, подобно администратору заглушек, не имеет никакой априорной информации ни об одним из интерфейсов СОМ. Однако администратор заместителей знает, как реализовать три метода IUnknown. Любые дополнительные вызовы AddRef или Release просто увеличивают или уменьшают на единицу внутренний счетчик ссылок в администраторе заместителей и никогда не передаются с использованием ORPC. Последний Release в администраторе заместителей уничтожает заместитель, посылая в апартамент объекта требование о прекращении связи. Запросы QueryInterface в администраторе заместителей обрабатываются несколько иначе. Подобно администратору заглушек, администратор заместителей не имеет никакой априорной информации об интерфейсах СОМ. Вместо этого администратор заместителей должен загружать интерфейсные заместители, выставляющие тот интерфейс, на который в данный момент идет запрос. Интерфейсный заместитель преобразует вызовы метода в запросы ORPC. В отличие от администратора заглушек, администратор заместителей является непосредственно видимым для программистов, и для обеспечения правильных отношений идентификации интерфейсные заместители агрегируются в идентификационную единицу администратора заместителей. Это создает у клиента иллюзию, что все интерфейсы выставляются одним СОМ-объектом. На рис. 5.4 показаны отношения между администратором заместителей, интерфейсными заместителями и заглушкой.

Сущность технологии СОМ. Библиотека программиста fig5_4.jpg

Как показано на рис. 5.4, заместитель связывается с заглушкой через третий объект, называемый каналом. Канал – это поддерживаемая СОМ обертка вокруг слоя RPC на этапе выполнения. Канал выставляет интерфейс IRpcChannelBuffer

[ uuid(D5F56B60-593B-101A-B569-08002B2DBF7A), local, object ]

interface IRpcChannelBuffer : IUnknown {

// programmatic representation of ORPC message

// программное представление сообщения ORPC

typedef struct tagRPCOLEMESSAGE {

void *reserved1;

unsigned long dataRepresentation;

// endian/ebcdic

// endian /расширенный двоично-десятичный код

// для обмена информацией

void *Buffer;

// payload goes here

// полезная нагрузка идет сюда

ULONG cbBuffer;

// length of payload

// длина полезной нагрузки

ULONG iMethod;

// which method?

// чей метод?

void *reserved2[5];

ULONG rpcFlags;

} RPCOLEMESSAGE;

// allocate a transmission buffer

// выделяем буфер для передачи

HRESULT GetBuffer([inl RPCOLEMESSAGE *pMessage,

[in] REFIID riid);

вернуться

1 Логически администратор заглушек обрабатывает удаленные вызоны методов IUnknown. Фактически, однако, эта задача выполняется тем объектом апартамента, который выставляет интерфейс IRemUnknown.