M. Barbaro, G. Rorato Client/Server 1 INTRODUZIONE Nella maggior parte dei casi le domande tipiche riguardo la tecnologia client/server sono: Qualsiasi processo distribuito è client/server? In un’applicazione client/server c’è sempre un database-server? Tutti i client devono fornire una GUI (Graphical User Interface)? Solitamente le “credenze popolari” tendono a rispondere affermativamente a tutte queste domande, soprattutto perché si pensa al server come a un data-base e ai client come ad applicazioni usate per interrogarlo tramite una GUI. Essendo una tecnologia nuova non è facile darle un formalismo preciso, e tali supposizioni (errate) sono giustificabili, soprattutto per il fatto che gli usi più comuni della tecnologia client/server coinvolgono proprio un database-server. Altre convinzioni tipiche sono che il server sia una macchina necessariamente più potente del client, ma ciò non è sempre vero. Infine, molto spesso si tende a fare confusione fra server e processo server. Teoria dei Client/Server 1 M. Barbaro, G. Rorato Client/Server Servizio: è un’entità software con il compito di fornire delle funzionalità specifiche a client sconosciuti a priori. Non dev’essere necessariamente ristretto ad una sola macchina, ma può essere implementato in modo distribuito. Server: Parte del servizio fornito da una singola macchina (anche tutto nel caso sia l’unica macchina). Nell’ambito dell’architettura client/server ha un comportamento di tipo reattivo, vale a dire che le sue azioni sono reazioni a eventi generati da un client (il server non esegue delle operazioni spontaneamente). Client: Entità software che sfrutta il servizio diventandone il cliente; può accedere a uno o più servizi contemporaneamente utilizzando una serie di operazioni che ne costituiscono l’interfaccia (interfaccia per il client). Nell’ambito dell’architettura client/server ha un comportamento di tipo propositivo, “evolve” in modo indipendente ed autonomo e, solo all’occorrenza, richiede delle funzionalità al server. Quindi, siamo dinanzi ad un’architettura client/server quando un’applicazione, il client, chiede qualche cosa mentre un’altra, il server, risponde a quella cosa: entrambe le applicazioni non hanno scopo di esistere isolatamente. Un esempio di servizio formato da più macchine si ha quando si va ad uno sportello Bancomat; il client è lo sportello e il servizio è il ritiro automatico di denaro; i server sono almeno uno per banca affiliata al servizio interbancario. Le entità delle diverse classi comunicano in qualche modo; questa comunicazione può essere vista come una relazione di tipo molti-a-molti in generale, ma può essere anche molti-ad-uno. Infatti: Un client può aver bisogno di più servizi; Un server può offrire un servizio a più client. La comunicazione avviene attraverso l’idea di transazione, cioè una sequenza di coppie ben definita del tipo: < richiesta, responso > Si usa il termine “responso” al posto del più scontato “risposta” perché si intende una risposta che non trasporta necessariamente dati “palpabili”, ma che potrebbe essere un esito su come sia andata una certa operazione. Un aspetto che salta subito all’occhio è la cooperazione fra due o più entità; cioè un unico compito svolto in comune cooperazione. In un buon sistema client/server, le due “entità” svolgono questo compito in modo equo, cioè distribuendosi in modo equo i carichi di lavoro. Gli emulatori di terminale nei mainframe, ad esempio, non soddisfano tale proprietà, ma ciò verrà chiarito più avanti. In generale, un sistema per essere realmente client/server deve soddisfare queste due proprietà: 2 M. Barbaro, G. Rorato Client/Server Il server è reattivo, cioè non esegue compiti per suo conto (e spontaneamente) ma reagisce agli stimoli esterni dei client; il processo server ha ragione di esistere se e solo se è presente almeno un client. Il client è proactive, “propositivo”, cioè evolve di sua iniziativa e all’occorrenza richiede funzionalità ad un server; il processo client non ha ragione di esistere se non esiste almeno un server. Tutto ciò che non soddisfa tali requisiti non può essere chiamato client/server. Il modello client/server è uno dei tanti modelli di applicazioni distribuite. Richiamo di concetti relativi ai Sistemi Operativi Processo: il primo termine chiave è processo, cioè un programma (inteso come sequenza di codice) in esecuzione. Formalmente è una coppia ordinata: < spazio di indirizzi, stato > Dove con spazio di indirizzi s’intende l’insieme delle informazioni, codice e dati, del programma e S il vettore di stato del programma (registri della cpu, stato del processore, program-counter, …). Thread: i thread (light-weight process) sono l’unità base d’utilizzo della cpu all’interno di un processo (un processo, infatti, può contenere più thread) che permette un’esecuzione basata sulla condivisione delle risorse e sulla differenziazione del flusso di codice all’interno di un unico processo. Ogni thread evolve in modo logicamente separato dagli altri in quanto è formato da un program-counter, da un insieme di registri e da uno stack ma, poiché condivide con i thread ad esso associati (ossia con quelli dello stesso processo) lo spazio d’indirizzamento (il codice, i dati, le risorse, …) oltre alle risorse fornite dal Sistema Operativo (file aperti, segnali, …) può interagire con loro alternandosi nell’esecuzione senza che venga commutato lo spazio di indirizzi corrente. La presenza di thread in un processo modifica la definizione di quest’ultimo in: < address space, < S1, …, Sn > > Infatti un thread è un flusso di esecuzione all’interno di un processo; vengono detti “processi leggeri” in quanto il cambio di contesto di un thread all’interno di uno stesso 3 M. Barbaro, G. Rorato Client/Server processo è (di norma) meno complesso a livello computazionale della commutazione tra diversi processi. L’efficienza, in termini computazionali e funzionali, data dai thread è effettiva solo se sono definiti a livello di Sistema Operativo; molti linguaggi li offrono a livello utente, e ciò non implica che lo “scheduling” sia fatto a livello kernel. Task: è sinonimo di processo. Viene usato questo termine per evidenziare la differenza fra thread e thread di uno stesso processo. Un task è un insieme di più thread (che insieme formano un processo) unito all’ambiente da essi condiviso (codici, dati, risorse, …) ossia un unico spazio d’indirizzamento affiancato da molti stati d’esecuzione. Sistema multiprogrammato È un sistema che permette la presenza di più programmi in memoria contemporaneamente. Più in dettaglio, la multiprogrammazione è un meccanismo che permette di aumentare l’utilizzo della CPU organizzando i job (gruppo di istruzioni/mansioni che devono essere svolte per far girare un programma) in modo da mantenerla sempre attiva: non appena il job in esecuzione entra in attesa di qualche evento del Sistema Operativo lascia l’esecuzione ad un altro job presente in memoria e pronto per essere eseguito. Sistema multitasking È un sistema che permette la presenza di più programmi in esecuzione contemporaneamente. È l’esecuzione logica della multiprogrammazione in cui più job vengono eseguiti, dalla, cpu, ad una frequenza tale da permettere agli utenti di interagire con ciascun programma durante la sua esecuzione. Sistema multiprocessing È un sistema in cui c’è l’esecuzione contemporanea di più processi grazie alla presenza di più cpu. Tali sistemi multiprocessore possono utilizzare due diversi modelli: Simmetrico Ciascun processore esegue una copia (che può comunicare con le altre, se necessario) identica del Sistema Operativo: con tale metodo il Sistema Operativo sfrutta quindi la presenza di più cpu senza dar loro alcuna gerarchia; non vi è dipendenza; 4 M. Barbaro, G. Rorato Client/Server Asimmetrico Con tale metodo le cpu vengono suddivise attraverso una gerarchia master/slave, ad ogni processore viene assegnato un compito specifico: ogni processore slave esegue un compito assegnatogli da un processore master che coordina il lavoro. Sistema Tightly-Coupled Questo sistema detto “tightly coupled” (strettamente accoppiato) è un sistema multiprocessore con condivisione di bus, clock e, talvolta, dei dispositivi di memoria e di quelli periferici. Sistema Loosely-Coupled Questo sistema detto “loosely coupled” (debolmente accoppiato) è un sistema multiprocessore in cui ciascun processore dispone di una propria memoria e comunica con gli altri tramite bus o linee telefoniche. In genere i sistemi distribuiti reali, sono sistemi “loosely coupled”, e macchine diverse eseguono un Sistema Operativo in modo da cooperare fra di loro. IPC (Inter Process Comunication) Un concetto fondamentale nella comunicazione fra processi è l’IPC (Inter Process Comunication). È un meccanismo implementato dal Sistema Operativo che fornisce gli strumenti per la comunicazione tra processi cooperanti e la sincronizzazione delle loro azioni; tale meccanismo si basa su uno dei seguenti principi: scambio di messaggi oppure memoria condivisa (con utilizzo di semafori o monitor). Processi cooperanti Due processi sono detti cooperanti quando sono in esecuzione concorrente e comunicano con l’IPC; il loro periodo di esecuzione deve, pertanto, sovrapporsi. Le tecniche di comunicazione usate possono essere classificate in due modi: Memoria condivisa; Memoria non condivisa (distribuita). Nella prima classe cadono, ad esempio, i semafori (e ciò da essi astratto). Nella seconda, sono presenti le tecniche di message-passing (diretta o indiretta). Un altro tipo di comunicazione (molto statica), di tipo condivisa, è il file-locking; un esempio è dato da Access (che non è un DB-server), il quale, quando due macchine diverse vogliono accedere ad uno stesso file *.MDB, crea un file di “lock” *.LCK, in cui tiene traccia delle informazioni per permettere l’accesso concorrente al database. 5 M. Barbaro, G. Rorato Client/Server Concetti relativi ai processi distribuiti I processi distribuiti sono classificati in un certo modo, che ora vedremo: Peer; Filtri; Server; Client. I processi distribuiti sono presenti quando esiste una comunicazione fra diversi processi. Processi filtro Un filtro è un processo che in generale ripropone non solo il data stream ma anche il risultato d’interrogazioni Client/Server. Un caso particolare di filtro e’ il processo che si trova in mezzo ad altri due processi e che ha il compito di riproporre al secondo il data-stream uscente dal primo, dopo averlo filtrato. Figura 1 Schema di un processo filtro. È importante capire che P1 e P2 non sono consci della presenza del filtro; inoltre P1 non è server per il filtro, e quest’ultimo non lo è per P2 (infatti, non sono reattivi). Ad esempio, il comando UNIX: 6 M. Barbaro, G. Rorato Client/Server Tale comando manda in stampa la lista delle directory e dei file, cioè il data-stream uscente dall’istruzione Ls viene filtrato e riproposto al comando lpr. Processi peer Due (o più) preocessi sono detti peer (pari) quando sono molto “simili” (se non addirittura cloni dello stesso processo) e comunicano con un protocollo noto ad entrambi; sono in cooperazione bilanciata per svolgere una funzionalità. Figura 2 Schema di processi peer. Processi Client/Server Il termine peer compare alla base di una comunicazione client/server, ma le due cose non vanno confuse. Ad esempio, l’IBM SNA (System Network Architecture) intende per “peer” ogni processo che è indipendente da una qualche “entità superiore” (non subordinato ad un mainframe). Questi nodi indipendenti sono tutti peer (“Physical Unit”) e parlano fra di loro attraverso canali (“Logical Unit”). È ovvio che un’applicazione client/server in tal caso corrisponde a peer cooperanti. Un altro esempio di peer è dato dai “transport layer” di un protocollo ISO/OSI. I peer hanno quindi uguali funzionalità, anche se a livello di codice sono “diversi”. Un sistema Client/server può essere schematizzato come in Figura 3. 7 M. Barbaro, G. Rorato Client/Server Figura 3 Schema di processi Client/Server. Tra questi processi lo scambio di messaggi inizia per iniziativa del client, che invia le richieste ad un server o a più server. La particolarità di un tale “messaging” è che è transazionale, ovvero composto da coppie ben definite di richieste e responsi. 8