Post on 01-May-2015
transcript
Component Object Model (COM) &
Distributed COM (DCOM)
Appunti di Windows & Dynamic Data Exchange (DDE)
(1987)
Object Linking and Embedding 1 (OLE 1) & Dynamic Data Exchange (DDE)
(1992, 1993)
COM, OLE2, ActiveX (Windows NT 4.0)
(1995)
Elaborazione Distribuita(anni ’80)
Open Software Foundation (OSF)Remote Procedure Calls (RPC)
(1992)
DCOM (1996)
Ragioni dello sviluppo COM
Applicazioni software di dimensioni sempre più grandi
Lunghi tempi per lo sviluppo e la manutenzione
Difficoltà nel rimuovere o aggiornare singole applicazioni che interagiscono con altre applicazioni
Necessità di:
Semplificare la progettazione e lo sviluppo di applicativi
Facilitare e standardizzare l'interazione tra applicazioni di diversi produttori
Caratteristiche del modello COM
COM è una specifica
http://www.microsoft.com/com/resources/comdocs.asp
COM è una “filosofia di programmazione”
Programmazione basata su componenti riciclabili
COM è uno standard di interoperabilità binaria
COM è un “collante” tra componenti, permettendo la loro interazione
Componente una parte di software riutilizzabile in forma binaria (non è
un codice sorgente !!!)
Suddivisione di un progetto in componenti I componenti possono essere facilmente integrati con
componenti prodotti da altri fornitori Un componente permette di accedere alle proprie
funzionalità tramite le “interfacce” Esempi di componenti: pulsanti, correttori ortografici
Caratteristiche del modello COM
L’utilizzo di un componente da parte di una applicazione non comporta la ricompilazione, visto che il componente che deve essere riutilizzato è già in versione binaria Ad esempio un word processor che usa un correttore
ortografico
Un componente è riutilizzabile Chi produce un componente può riutilizzarne uno già
esistente, utilizzando due tecniche: containment e aggregation
Caratteristiche del modello COM
Gestione delle versioni Si è superato il problema delle dll:
un programma che utilizza una dll può interrompersi se trova una versione diversa di dll
In COM non è possibile cambiare le caratteristiche ("interfaccia") dei componenti già esistenti.
La nuova versione di un componente COM deve presentare le stesse interfacce, aggiungendone altre
Ad esempio se voglio realizzare un correttore ortografico diverso da quello offerto da word, devo garantire le stesse interfacce originarie, aggiungendone altre se voglio
Caratteristiche del modello COM
Sono tecnologie create sulla base di COM e della sua architettura
ActiveX utilizza anche la tecnologia OLE v.2.0 La principale e visibile caratteristica dei documenti
ActiveX è la possibilità di aprire una finestra all’interno di un’altra applicazioneAd esempio Explorer nei confronti dei documenti Word o
Acrobat
Tecnologie ActiveX e OLE 2
COM
OLE 2ActiveX
Ogni oggetto COM è un’istanza di una particolare classe
Ogni oggetto COM presenta una o più interfacce Ogni interfaccia include uno o più metodi che
possono essere invocati dal programma client Per invocare uno di questi metodi il client deve
possedere un puntatore all’interfaccia che contiene i metodi
Oggetti COM
Oggetto COMClient
AddToDictionary()
RemoveFromDictionary()
Interfaccia
Metodi
Ogni interfaccia ha due nomi: Stringa di caratteri. Deve iniziare con la lettera “I” Globally Unique Identifier (GUID), chiamata Interface
Identifier (IID) o Universal Unique Identifiers (UUID) GUID è di 16 byte ed è ottenuta eseguendo un apposito tool GUID contiene un time stamp (tutti i GUID generati nella stessa
macchina saranno diversi) GUID contiene il MAC address (o un numero casuale se non vi è
una scheda) per differenziare GUID generati da macchine diverse
La specifica delle interfacce (non l’implementazione) avviene in un linguaggio comune: Interface Definition Language (IDL) Deriva dall'IDL usato in Microsoft RPC
Interfacce degli Oggetti COM
[object,
uuid(E7CD0D00-1827-11CF-9946-444553540000)]
interface IMyInterface : IUnknown {
import “unknwn.idl”;
HRESULT LookUpInt([in] int c, [out] boolean *found);
HRESULT SumOfIntegers([in] myinteger[5], [out] int *sum);
}
L'interfaccia IMyInterface eredita tutti i metodi definiti in IUnknown Un client in possesso del puntatore a IMyInterface può invocare anche i
metodi di IUnknown I metodi dell'interfaccia IUnknown devono essere sempre presenti !
Il comando import specifica il file idl che descrive IUnknown LookUpInt e SumOfIntegers sono i metodi forniti dall'interfaccia
IMyInterface HRESULT è un valore di ritorno standard relativo al successo/insuccesso [in], [out] parametri formali ingresso e uscita (esistono anche quelli
ingresso/uscita [in, out])
Esempio di Interface Definition Language
Una volta che una interfaccia è stata definita e rilasciata nel "mondo", essa non può più essere cambiata.
Non è possibile cambiare/aggiungere/modificare metodi o parametri.
L'unica soluzione è definire una nuova interfaccia (nuovo nome e IID) che possiede gli stessi metodi della vecchia interfaccia, aggiungendone altri nuovi.
Alcune Regole sulla Definizione delle Interfacce
La descrizione dell'interfaccia non è sufficiente per il suo uso da parte di un generico client
Il client possiede solo il puntatore all'iterfaccia
In genere per invocare un metodo, un client deve sapere come fare (ciò in genere dipende dal linguaggio in cui è stato scritto il metodo)
Esiste una struttura binaria (SEMPRE LA STESSA) per l'accesso ai metodi di una interfaccia di un oggetto COM. Standard binary interface format
La presenza di uno standard binary interface format implica che il client possa invocare un metodo di un oggetto senza dover tener conto del linguaggio in cui è stato scritto il metodo stesso
Definizione delle Interfacce:
Standard binary format
Esempio di Interface Definition Language
Client Pointer Method 1
Pointer Method 2
Pointer Method 3
Pointer Method 4
Pointer Method 5
QueryInterface() { ……}
AddRef() { ……}
Release() { ……}
LookUpInt() { ……}
SumOfInteger() { ……}
vtable
Puntatore Interfaccia IMyInterface
Internal Pointer to vtable
(1)
(2)
1) Metodi interfaccia IUnknown (sempre presenti)
2) Metodi interfaccia IMyInterface
La struttura binaria appena vista suggerisce che la realizzazione più "immediata" e "naturale" di un client COM si ottiene utilizzando il C++ è necessario implementare la gestione dei puntatori a
vtable per l'invocazione dei metodi Scrivere un client in C è possibile, ma più difficile L'assenza di meccanismi per la gestione dei puntatori in VB
ha determinato la necessità di creare una speciale interfaccia vtable chiamata IDispatch
Definizione delle Interfacce:
Standard binary format
Tutti gli oggetti COM la devono implementare
Contiene tre metodi: QueryInterfaceAddRefRelease
Interfaccia Fondamentale IUnknown
Quando il client crea un oggetto COM (come ? si vedrà dopo), riceve il puntatore ad una delle sue interfacce (quella richiesta dal client) Con tale puntatore il client può invocare tutti i metodi
dell'interfaccia E se vuole invocare metodi appartenenti ad altre interfacce ?
Ci sono casi in cui un client non crea un oggetto COM, ma un altro client gli passa (cede) il puntatore ad un'interfaccia di un oggetto COM già creato Con tale puntatore il client può invocare tutti i metodi
dell'interfaccia E se vuole invocare metodi appartenenti ad altre interfacce ?
Interfaccia Fondamentale IUnknown
Metodo QueryInterface
Attraverso il puntatore all’interfaccia, il client accede al metodo IUnknown::QueryInterface
Specifica l’IID dell’interfaccia che gli necessita Se l’oggetto COM supporta l’interfaccia richiesta, il client riceverà il
puntatore all’interfaccia richiesta e potrà utilizzarne i metodi.Altrimenti passerà NULL
Interfaccia Fondamentale IUnknown
Metodo QueryInterface
Client Oggetto COM
A
B
1. Il Client usa il puntatore a A per richiedere il puntatore a B, invocando la QueryInterface (IID_B)
2. L'Oggetto ritorna il puntatore a B
3. Il Client può invocare i metodi dall'interfaccia B
Supponiamo che esista un tool di analisi di testo implementato come oggetto COM e che esso abbia un'interfaccia ISpellCheck
Una volta installato l'oggetto nel mio sistema, il mio word processor (e qualunque altro client) lo può utilizzare: interroga la QueryInterface e chiede del puntatore a ISpellCheck
Supponiamo che venga rilasciata una nuova versione dell'oggetto che ora comprende anche l'interfaccia IThesaurus (semantica & sinonimi)
Se uso il nuovo oggetto con l'esistente versione di word allora la nuova interfaccia sarà del tutto ignorata
Installando la nuova release del word processor, esso potrà chiedere sia il puntatore a ISpellCheck sia a IThesaurus (tramite la QueryInterface)
Se installo la nuova versione di word e mantengo il vecchio oggetto, tutto funziona ancora bene, perché se il mio word chiederà alla QueryInterface il puntatore a IThesaurus, otterrà NULL e l'opzione Thesaurus nel menù sarà disabilitata
Interfaccia Fondamentale IUnknown
Esempio di Utilizzo Metodo QueryInterface
Ogni oggetto COM è implementato dentro un Server Il Server supporta più oggetti di una determinata classe
Il Server contiene il codice dei metodi delle interfacce dell'oggetto
Il Server ha il compito di creare l'oggetto Gestisce i dati di ciascun oggetto
E' possibile avere tre diversi tipi di oggetti COM in base al tipo di Server che li supporta: In-Process Local Remote
Dal punto di vista del Client non vi è alcuna differenza
Tipi di Componenti
Componenti In-process Il Server In-Process condivide lo stesso spazio degli
indirizzamenti del Client Il Server In-Process viene implementato come dll Vantaggio: velocità di elaborazione (nessun passaggio di
contesto) Svantaggio: essendo una dll e non exe, può essere
impiegato solo nel contesto di un programma chiamante e non può essere eseguito come applicazione autonoma
Tipi di Componenti
Componenti Locali Il Server risiede sullo stesso computer del Client, ma
viene eseguito come processo autonomo (spazio di indirizzi differente)
Il Server locale viene implementato come exe Svantaggio: cambio di contesto dal processo chiamante al
componente
Componenti Remoti Il Server risiede su un computer diverso da quello in cui
viene fatto eseguire il client (processo che utilizza il componente)
Lo scambio informativo remoto viene supportato da DCOM
Tipi di Componenti
Finora si è assunto che un client possegga un puntatore ad una interfaccia iniziale di un oggetto COM
Dobbiamo capire come sia possibile creare un oggetto COM e come un client possa acquisire il puntatore ad una delle interfacce di tale oggetto
La creazione di un oggetto COM è basata su:Esistenza di Class Identifier (CLSID).
Ogni oggetto COM è una istanza di una classeOgni classe è identificata da un Class Identifier
(CLSID)
Esistenza di una COM Library di supporto
Creazione di un Oggetto COM
Ogni sistema che supporta COM deve fornire un'implementazione della COM Library
La COM Library fornisce funzioni di supporto ad oggetti COM e ai client ad esempio quelle per creare un oggetto COM
Le funzioni della COM Library sono accessibili tramite semplici chiamate di funzioni non si usano metodi delle interfacce COM
Il nome di una funzione della COM Library generalmente inizia con il prefisso Co- ad esempio CoCreateInstance
Creazione di un Oggetto COM:
COM Library
La creazione di un oggetto COM implica la produzione di una istanza della classe dell'oggetto
Ciò viene realizzato tramite l'avvio del Server relativo alla classe stessa Tale Server è l'unico in grado di istanziare l'oggetto COM E' necessario avviarlo solo per la prima istanza
dell'oggetto
E' compito della COM Library avviare il Server e passargli l'ordine di creare l'istanza dell'oggetto
La creazione di un oggetto COM e l'inizializzazione dell'istanza sono due fasi separate
Creazione di un Oggetto COM:
COM Library
La COM Library necessita di un "Registro di Sistema" in cui venga associato ad ogni CLSID il percorso del codice del Server
L'implementazione del "Registro di Sistema" dipende dal SO Windows NT utilizza il Registry In ogni caso il "Registro di Sistema" deve contenere:
CLSID (key-entry) Tipo di server (in-process, local, remote) Percorso relativo alla DLL o EXE (percorso locale o
remoto) Il "Registro di Sistema" viene aggiornato ad ogni installazione
di una applicazione
Creazione di un Oggetto COM:
COM Library
Il Client invoca la funzione “CoCreateInstance” della COM Library, passando: il CLSID (classe desiderata) l’IID (identificatore dell’interfaccia desiderata)
Sulla base del CLSID ed utilizzando il "Registro di Sistema", la COM Library: Localizza il Server in grado di istanziare la classe dell'oggetto Il Server viene attivato (se non lo è già) Il Server crea l'istanza dell’object class desiderata, passando
alla COM Library il puntatore all’interfaccia richiesta La COM Library passa questo puntatore al client
Creazione di un Singolo Oggetto COM
In-Process e Locale
Il Client invoca la funzione “CoCreateInstance” della COM Library, passando il CLSID e IID
Sulla base del CLSID ed utilizzando il "Registro di Sistema", la COM Library:
localizza il Server (Remoto) in grado di istanziare la classe dell'oggetto
Viene contattato il Sistema Remoto per realizzare l'istanziazione (via RPC)
Il Sistema remoto controlla il suo Registro ed individua il server Il Server viene attivato (se già non lo è) Il Server crea l'istanza dell’object class desiderata, restituendo al
Sistema Remoto il puntatore all’interfaccia richiesta Il puntatore viene consegnato al client via RPC
Creazione di un Singolo Oggetto COM
Remoto
Se l’utente deve creare una sola istanza di un oggetto, allora la CoCreateInstance è sufficiente
Molto spesso capita che l’utente necessita di istanze multiple di oggetti della stessa classe
In tal caso viene utilizzato l’oggetto COM “Class Factory” Il Class Factory è un oggetto COM in grado di creare più
oggetti COM appartenenti ad una specifica classe Il nome non è molto appropriato, perché vengono creati
oggetti non classi
Creazione di Oggetti Multipli
Class Factories
L'oggetto "Class Factory" viene gestito come un qualunque altro oggetto COM (accesso tramite interfacce) e deve possedere almeno l’interfaccia IClassFactory
In realtà la CoCreateInstance si basa sull'oggetto Class Factory e sull'interfaccia IClassFactory, ma ciò viene del tutto mascherato all'utente
Creazione di Oggetti Multipli
Class Factories
Client
Class Factory
Server
:: CreateInstance()
:: LockServer()
IClassFactory
L’interfaccia IClassFactory contiene due metodi: CreateInstance. Crea una nuova istanza della classe di
oggetto che la Class Factory può istanziare. LockServer.
Per attivare un oggetto Class Factory, il client invoca la funzione della COM Library: CoGetClassObject Specifica il CLSID della classe di oggetti che l’oggetto
Class Factory dovrà istanziare Specifica l’IID dell’interfaccia per l’accesso a Class
Factory (IClassFactory) La COM Library crea l'oggetto Class Factory della classe
desiderata e fornisce al Client il puntatore richiesto (IClassFactory)
Creazione di Oggetti Multipli
Class Factories
Creazione di Oggetti Multipli
Class Factories Il Client ha già invocato la funzione CoGetClassObject e la COM Library ha fatto
partire la Class Factory e ha fornito al Client il puntatore ad una sua interfaccia (ad esempio IClassFactory)
Client
Server
Class Factory
Object
A
2
1.IClassFactory::CreateInstance(IID_A)
3.Puntatore interfaccia A
IClassFactory
4. Il Client può invocare i metodi dell'oggetto
Quando un oggetto COM viene creato, esso ha dati non inizializzati
Il Client potrebbe aver di bisogno l’inizializzazione di dati (ad esempio salvati sul disco) E' ovviamente necessario che i dati siano salvati in modo
persistente
In tal caso, la prima interfaccia che il Client chiederà è quella contenente le funzioni di inizializzazione dell’oggetto.
Esistono interfacce standard a tale scopo (utilizzo di dati salvati in files): IPersistFile, IPersistStorage, IPersistStream
Inizializzazione di un Oggetto COM
La soluzione più ovvia: il client che ha creato un oggetto lo distrugge. Ciò non è possibile ! Spesso un client passa il puntatore all’interfaccia di un
oggetto ad un altro client (che può fare lo stesso con altri client)
Ogni client non sa quanti altri client stanno utilizzando lo stesso oggetto
Solo l’oggetto può sapere quando nessun client lo utilizza più
Vengono utilizzati i metodi dell'interfaccia IUnknown: IUnknown::AddRef() IUnknown::Release() basati sul Reference Counting
Distruzione di un Oggetto COM
Ogni oggetto COM che viene creato, mantiene un Reference Count
Quando l’oggetto COM passa il puntatore ad una sua interfaccia ad un client, incrementa di 1 il Reference Count
Quando un client termina l'utilizzo l'oggetto, deve invocare il metodo IUnknown::Release(), che decrementa di 1 il Reference Count
Quando un client riceve il puntatore da un altro client, invoca il metodo IUnknown::AddRef(), che incrementa di 1 il Reference Count
Se il Reference Count è 0, l’oggetto distrugge se stesso Problemi con i client che non rispettano la regola del
Reference Counting
Distruzione di un Oggetto COM
Reference Counting
Containment
Riuso di Componenti COM
AggregationOuter Object
Client
IUnknown
IUnknown
Inner
Object
A
B
Inner ObjectOuter Object
Client
IUnknown IUnknown
BA
Per invocare un metodo di un oggetto COM, il client deve possedere il puntatore all’interfaccia relativa al metodo (vtable)
Il puntatore è un indirizzo di memoria Per poter essere utilizzato, lo spazio degli indirizzi
deve essere lo stesso di quello del client Come viene utilizzato il puntatore nell’architettura
COM ? La risposta dipende dalla tipologia del server: in-
process, local e remote
Marshalling
E' il caso più semplice. Lo spazio di indirizzamento del client e del server è lo stesso Il puntatore all’interfaccia può subito essere utilizzato per
accedere al binario del metodo richiesto Il Passaggio dei parametri e i valori di ritorno è realizzato nel
modo tradizionale
Marshaling: In-process server
Client COM Object
In-process server
Client process
Se il client e l'oggetto COM risiedono nella stessa macchina, ma sono processi separati (spazio di indirizzi diversi), il client non può puntare all'interfaccia dell'oggetto
Si utilizzano due oggetti COM: Proxy e Stub
Un proxy è un oggetto COM, che presenta la stessa interfaccia dell’oggetto desiderato
Il client invoca il codice del proxy, che crea un package dei parametri del client e li invia tramite una interprocess communication (dipende dal SO)
Marshaling:Local Server
La richiesta arriva ad un altro oggetto COM: Stub Lo stub unpackage la richiesta e passa i parametri del
client all’oggetto reale Ogni risposta da parte dell’oggetto viene inviata nello
stesso modo al client
Marshaling:Local Server
Client Proxy
Client process
Stub Object
Server process
Single Machine
Interprocess
communication
Stesso schema del Local Server La comunicazione è basata su DCOM, utilizzando
RPC
Marshaling: Remote Server
Client Proxy
Client process
Stub Object
Server process
Machine X Machine Y
RPC
Cosa è il Marshaling ? Necessità di un formato standard per lo scambio di
parametri e risultati tra Proxy e Stub (soprattutto per i remote server) e di opportuno codice per eseguire le appropriate conversioni Macchine diverse possono usare codifiche e
rappresentazioni di dati diverse
Marshaling