cerca
Sistemi Operativi - Lezione del 19 Maggio 2008
modifica cronologia stampa login logout

Wiki

UniCrema


Materie per semestre

Materie per anno

Materie per laurea


Help

Sistemi Operativi - Lezione del 19 Maggio 2008

 :: Sistemi Operativi - Lezione del 19 Maggio 2008 ::

Torna alla pagina di Sistemi Operativi

Sistemi Distribuiti

Lezione 1 - Obiettivi & funzioni

Nei sistemi distribuiti, abbiamo diverse macchine connesse, con almeno 1 processore per sistema. La memoria è locale ad ogni sistema, e le periferiche possono essere:

  • una per sistema, ma usabili in rete
  • una per sistema, ma NON condivisibili in rete
  • globali, in rete
  • la rete stessa (eh sì è periferica anche lei)

Once upon a time, le reti erano composte da macchine e in generale hw tutto della stessa marca, a volte addirittura dello stesso modello.
Ai giorni nostri, invece, si tende a mettere insieme macchine eterogenee, perché le aziende si espandono e man mano comprano cose differenti. Per fortuna ci sono gli standard che ci permettono di far dialogare macchine e sistemi diversi.

Vediamo un po' di concetti:

  • sito = una locazione geografica, connessa da altri siti
  • a sua volta, il sito è composto da host|nodi|macchine|computer o qualche altro sinonimo, e questi possono essere:
    • server
    • client
    • entrambe le cose

Ecco invece i vantaggi di avere architetture distribuite:

  • posso usare macchine già esistenti per diverse funzioni (integrare sottosistemi)
  • condivisione delle risorse
  • parallelismo della computazione, in modo meno costoso rispetto all'aumentare la potenza di un singolo mainframe
  • interazione con l'utente: porto la potenza di calcolo sulla scrivania dell'utente, e non viceversa
  • riduzione complessità e costo: invece di aggiornare macchinone grosse, ne prendo altre e le metto in rete (downsizing)
  • reliability, fault tolerance, dependability (= aumento della disponibilità). Paroloni che tuttavia assumo siano noti
  • scalability

Sistemi Operativi per architetture di elaborazione distribuite

Così come il SO dovrebbe astrarre dalla macchina sottostante, anche i SO per archi distr dovrebbere permettere di astrarre dalla rete sottostante, e mostrarne le grazie al processo come tutte allocate a lui.

Ma dobbiamo distinguere tra due gradi di virtualizzazione:

Network Operating System = la struttura della rete è visibile. Il processo non si occupa dei dettagli della comunicazione, ma comunque la rete non è trasparente.

Distributed Operating System = è tutto trasparente all'utente.

Network Operating System

L'obiettivo di un NetSO è quello di permettere l'accesso alle risorse sulle varie macchine. Esse devono essere innanzitutto collegate, in qualche modo:

  • telnet
  • socket
  • RPC o RMI

Come vedremo poi, RPC non è un metodo per la comunicazione tra processi.

Per trasferire i files tra una macchina e l'altra, posso usare il protocollo applicativo FTP oppure un fileserver remoto.

Distributed Operating System

In questo modello, vogliamo che tutte le risorse siano accessibili come se fossero locali. A questo scopo, non basta montare il FS remoto: occorre che tutto, quindi compreso anche il FS locale, sia uguale per tutte le macchine della rete.

Questo deve potermi permettere di migrare i dati da una macchina all'altra, e di migrare processi da una macchina all'altra. Non si tratta di roba da poco, in effetti.

Migrazione dei dati

Posso ottenere questa virtualizzazione in diversi modi:

  • copia - lavoro - salvataggio: si copia in locale il file remoto, lo si spaciuga, e poi lo si risalva in remoto. Ovviamente tutto questo deve essere ignoto all'utente, ad esempio tramite FTP automatizzato.
  • copio parti di files e metto il lock su di esse.

Comune ad entrambe le modalità sono

  1. il problema dei lock distribuiti
  2. la compatibilità tra le rappresentazioni dei dati su macchine con architetture hw diverse

Il punto 2 mi dice, ad esempio, che una macchina little-endian dovrà lavorare in modo diverso sugli stessi dati, rispetto ad una macchina big-endian. Deve però pensarci il SO, e non l'utente, in modo trasparente (aggettivo quanto mai abusato...).

Migrazione della computazione

Ci sono due tipi di migrazione, per quanto riguarda la computazione: far migrare una procedura oppure un processo.

La migrazione di procedura consiste nell'RPC, o nell'RMI. Invio parametri ad una procedura, che viene eseguita su di un'altra macchina.

A che pro?

  • la macchina remota può avere caratteristiche hw o sw più adatte per quel particolare calcolo
  • devo lavorare su dati disponibili fisicamente su quella macchina, e invece di copiarli tutti da me per spaciugarli, è meglio far eseguire laggiù i miei conti.

Per migrare il processo, devo essere in grado di congelare l'evo della comp di un processo, copiarlo su un'altra macchina e ripartire da là senza che il processo se ne accorga, oppure usare dei misteriosi - finora - agenti mobili, che sono progettati apposta per andare in giro per il sistema.

Anche qui, le motivazioni che inducono a migrare i processi sono le stesse della migrazione delle procedure, con quest'aggiunta:

  • necessità di bilanciare il carico tra diverse macchine
  • velocità di elaborazione

Inoltre, il DistroSO deve avere anche un file server distribuito, al solito TRASPARENTE!!!

Robustezza

Possono accadere guasti o malfunzionamenti, ma lo show deve andare avanti come se nulla fosse. Ecco quindi che il sistema distribuito deve, in qualche modo:

  • rilevare i guasti
  • mascherarli
  • riconfigurare il sistema
  • ripristinare il sistema com'era prima del danno

Rilevamento dei guasti

Come si ottiene?

Potrei monitorare periodicamente le macchine, facendosi scambiare tra di loro dei protocolli di handshaking, così che si accorgano se un'altra sta soffrendo o no.

Posso implementare un timeout: se una macchina non risponde a certe sollecitazioni dopo un certo timeout, posso assumere che sia giù.

Posso, ancora, duplicare la computazione: ad esempio, faccio eseguire lo stesso compito a due macchine diverse, e confronto i risultati. Se qualcosa non coincide, è sintomo di qualche malfunzionamento. Infatti, è ben poco probabile che due macchine diverse presentino lo stesso problema, che conduca allo stesso tipo di guasto.

Mascherare gli errori

Gli errori non devono essere visibili, perché tutto deve procedere come se nulla fosse. Come faccio?

Posso replicare la computazione un numero dispari di volte. Basandomi sulla statistica presentata qui sopra, è improbabile che tutte le macchine presentino lo stesso problema. Inoltre, essendo in dispari, scelgo il risultato che la maggioranza mi dà, e sono praticamente certo che il calcolo è esatto.

Posso duplicare le risorse: raddoppio tutto, così ho abbastanza ridondanza da poter mascherare ogni cosa.

Riconfigurazione

Se cade un collegamento, o va giù una macchina, devo semplicemente togliere dalle tabelle di routing quella destinazione e/o percorso. Poi ci penserà qualcuno a rimettere in sesto il tutto.

Ripristino

Dopo aver riparato il guasto, le tabelle di instradamento vanno ripristinate, magari con l'handshaking di cui parlavo prima si informano le altre macchine del ritorno in vita, e si reinvia la posta arretrata (fondamentale...).

Aspetti progettuali

Quando si progetta un SO distribuito, occorre tenere a mente le seguenti cose:

  • garantire la trasparenza di allocazione delle risorse: processori, dichi, periferiche, files
  • garantire la mobilità di utenti, computazione e dati
  • garantire la tolleranza ai guasti
  • garantira scalabilità estensiva ed intensiva (al momento non ricordo la distinzione:D)

Quindi, occorre scrivere il tutto in MIXAL.

Lezione 1 (ancora?) - Gestione della comunicazione in rete

OCCHIO: tutto ciò che segue è roba damianesca. Inoltrarsi a proprio rischio e pericolo nella lettura. Eh, i bei tempi di quando i protocolli di rauting variavano di giorno in giorno...

Nomi e risoluzione dei nomi

Devo dare nomi univoci alle risorse (informative o fisiche), e ai processi, così che li so pescare in tutta la rete.

Devo quindi

  1. individuare la macchina
  2. individuare la risorsa su quella macchina

In astratto, è così:

 <nome host, identificatore>

Per quanto riguarda il nome host, posso usare gli indirizzi IP numerici, oppure i nomi logici ad essi associati.

La risoluzione dei nomi è quella branca della scienza che si occupa di collegare un nome ad un indirizzo. Le alternative, in questo campo, sono fondamentalmente 2:

  1. mantenere a mano una tabella per ogni computer
  2. appoggiarmi ai domain name server che ci pensano loro, tramite un protocollo apposta, a trovare le cose nella rete.

I DNS partono dal concetto di dominio, che è una suddivisione arbitraria della rete. Il protocollo DNS è distribuito: ogni server conosce i dettagli del proprio dominio, e sa solo a grandi linee dove andare a chiedere per il resto.

Sono organizzati in modo gerarchico: ci sono server sempre più dettagliati a partire dai dominî più generali. Ad esempio, www.swappa.it si raggiunge prima attraverso il DNS che gestisce tutti i .it, e poi tramite il DNS che gestisce swappa.

Per ottimizzare le prestazioni, i server DNS mantengono una cache delle informazioni richieste di recente, così che quando arriva una richiesta ad una stessa risorsa non devono chiedere ancora in rete. Ovviamente questa cache va tenuta aggiornata, e quindi rinfrescata ogni tanto.

Strategie di instradamento

Devo trovare un percorso da A a B. Se esiste un solo percorso, non ho scelta: uso quello. Se ne ho diversi, invece, devo scegliere quello che rende di più.

Ci sono 3 tipi di instradamento: statico, virtuale e dinamico.

Instradamento statico

Il percorso A-B è definito a priori, e non lo cambio più.

  • non si cerca niente in rete
  • ma se ci sono errori o se il carico su rete varia, mi arrangio

Instradamento virtuale

Il percorso A-B è scelto per ogni sessione. Per tutta la sessione di comunicazione, si usa quel percorso. È possibile che alla sessione successiva il percorso sia diverso.

  • si cerca l'instradamento solo all'inizio della sessione
  • non si adatta a variazioni di carico o a guasti durante la sessione: occorre aspettare la sessione successiva

Instradamento dinamico

Il percorso A-B è scelto per ogni messaggio, e si adatta a qualsiasi tipo di danno e variazione di carico.

Nei primi due tipi di instradamento, statico e virtuale, i messaggi vengono inviati in un certo ordine, e ricevuti nello stesso ordine.

Con l'instradamento dinamico, invece, no, perché è possibile che un messaggio spedito dopo abbia scelto una strada che lo fa arrivare prima a destinazione, rispetto alle strade scelte dai messaggi precedenti.

Ecco quindi che occorre gestire la faccenda di ricostruire i messaggi nell'ordine in cui sono stati spediti originariamente, anche se arrivano in ordine sparso.

Gateway

Serve per mettere in comunicazione 2 reti, anche se usano un protocollo diverso.

Per andare da host a gateway, in genere si usa l'instradamento statico. Infatti, il gateway difficilmente cambierà indirizzo in una rete. La dinamicità qui è inutile.

Al contrario, da gateway a host serve instradamento dinamico, perché se la rete è grossa è impensabile che il gateway conosca tutte le macchine della rete.

Rùter

Il rùter, a differenza del rauter di damianesca memoria, gestisce l'instradamento, ed è quindi più complesso di un gateway.

Strategie di pacchetto

Finora abbiamo parlato della strada che i messaggi devono prendere per arrivare a destinazione. Ma il messaggio può avere lunghezza variabile. E più è lungo, più è probabile che un'interferenza o un disturbo lo alterino.

La soluzione è dividerlo in pacchetti di dimensione fissa. Questi pacchetti in realtà hanno nomi diversi a seconda del protocollo che sto usando:

  • packet
  • datagram
  • frame

I pacchetti vengono inviati in ordine, e poi vanno riassemblati nel giusto ordine anche se arrivano sparsi. Devo poi saper gestire anche i reinvii, nel caso che un pacchetto arrivi errato o non arrivi del tutto. Come dicevamo prima, se il pacchetto è piccolo è meno probabile che sia soggetto a difetti di trasmissione.

Strategie di connessione

L'obiettivo è far parlare 2 processi che stanno a distanza. Come diavolo faccio? Devo creare un canale tra di essi, e ho 3 strategie diverse:

  • commutazione di circuito
  • commutazione di messaggio
  • commutazione di pacchetto

Commutazione di circuito

I 2 processi definiscono un percorso fisico tra di essi, e questo percorso rimane bloccato per tutta la sessione, e nessun altro lo può usare.

Le caratteristiche sono:

  • tanto tempo per l'attivazione
  • spreco eventuale di banda
  • facile però da gestire

E' quello che succede con la linea telefonica: si crea un circuito fisico tra la mia cornetta e quella dell'ascoltatore.

Commutazione di messaggi

Il collegamento tra i 2 processi rimane in vigore per tutta la durata dell'invio del messaggio. Il canale viene quindi creato dinamicamente, e c'è però un po' più overhead di gestione, perché per ogni messaggio devo creare il canale.

Commutazione di pacchetto

Ogni pacchetto segue una sua connessione. Qui la faccenda si fa complicata, perché è possibile che i pacchetti, come dicevamo prima, arrivino in ordine sparso e sia necessario ricomporli. Però uso al meglio la banda.

Gestione dei conflitti

Che conflitti?

I conflitti si hanno quando più macchine vogliono usare lo stesso canale di comunicazione.

Bus multi-accesso

E' in sostanza il cavo di rete.

Se ricordate dal Damiani, le collisioni sono autorilevate tramite il controllo: se quello che ricevo è uguale a quello che invio, allora tutto ok, se no c'è stato un errore. Le varie periferiche sanno gestire autonomamente questi casi, tramite il reinvio dopo un tempo più o meno casuale dei messaggi.

Per evitare troppe collisioni, devo porre un limite al numero di nodi.

Rete ad anello

C'è un token che gira per le macchine: quando una macchina riceve il token, manda i suoi messaggi, poi passa il token ad altri.

Occorre avere strategie per recuperare nel caso in cui i token si perdano o si rovini. In genere si usa un timeout: se entro tot tempo il token non riappare, viene dato per morto e si riparte.

Lezione 2 - Protocolli di comunicazione

I driver del SO devono, purtroppo per loro, occuparsi dell'implementazione dei protocolli di comunicazione. Ecco perché ci occorre sapere come sono fatti sti protocolli, per poterli implementare...

I problemi che devo affrontare sono questi:

  • comunicazioni asincrone
  • possibilità di errori nella comunicazione
  • macchine eterogenee

E al solito, voglio un ambiente omogeneo e astratto rispetto a tutto sto casino. In altre parole, voglio realizzare una virtualizzazione della comunicazione: non devo vedere tutti i canali e i messaggi etc., voglio solo che i 2 processi vedano un canale virtuale, con i dettagli scabrosi nascosti.

Il modello astratto che si segue è quello ISO / OSI, composto da diversi strati:

  1. strato fisico = come trasmettere i bit: dettagli meccanici ed elettrici, come connettori, portante etc.
  2. data link = gestire invio e ricezione del singolo pacchetto, con rilevazione di eventuali errori
  3. strato di rete = gestisce la connessione, l'instradamento in uscita e in entrata (l'IP)
  4. strato di trasporto = gestisce la partizione dei messaggi in pacchetti, li riassembla, ne controlla il flusso e gli errori (TCP)
  5. strato di sessione = realizza l'instradamento tra 2 processi
  6. strato di presentazione = converte i dati nella forma adatta alle varie macchine; gestisce la duplex-icità dei flussi (invio e ricezione contemporanei)
  7. strato di applicazione = i vari protocolli applicativi: ftp, smtp, http, puputp, hellokittytp etc.

ISO / OSI è una pila (scarica:)). I vari strati, a partire da quello più alto, aggiungono info per trasformare il messaggio in qualcosa di accettabile. Se lo vedo al contrario, invece, a partire dal basso i dati vengono incapsulati in strutture più grandi per renderli appetibili agli strati superiori.

Quindi, un messaggio parte dallo strato di applicazione, si inciccisce e divide etc. fino a diventare bit, e dall'altro lato fa la strada inversa, dimagrendo fino a tornare quello che era.

I modelli reali si discostano un po' da questo modello teorico, perché

  1. è complicato
  2. è stato inventato dopo che i modelli reali erano già stati implementati:)

Tanto per ricordare, il TCP realizza le connessioni, ed è affidabile (se c'è un errore, si cerca di rimediare). Invece UDP non realizza connessioni ed è inaffidabile.

I driver di rete sono quei software che nel mio SO realizzano questi protocolli di comunicazione in rete, siano essi ISO / OSI o altra roba.

Computazione distribuita

Lezione 1 - Distribuzione della computazione

Quello che voglio è sfruttare, finalmente, questo benedetto parallelismo tra macchine diverse. E poi, siccome ho i dati spantegati su varie macchine, sarebbe bello se il mio processo andasse in esecuzione proprio su quella macchina, così che i dati li ha subito disponibili.

In generale, dovrei poter spostare la computazione sulla macchina che ha le risorse adatte per quel tipo di processo. Risorse intese in astratto: CPU, memoria, dotazione HW e SW.

Per supportare la computazione distribuita, mi serve poter

  • comunicare
  • sincronizzare

i processi distribuiti.

Lezione 2 - Chiamata di procedura remota (RPC)

L'idea è di eseguire la procedura laddove essa può essere eseguita meglio. Il resto del processo rimane altrove.

In questo scenario, l'entità attiva è il processo chiamante, mentre quella passiva è la procedura chiamata, che "dorme" finché non viene risvegliata da qualcuno.

Il processo chiamante deve avere disponibile uno stub, cioè un abbozzo di come è fatta la procedura remota, di quali parametri vuole etc. etc. Ha quindi una rappresentazione della procedura.

Deve però poi essere il SO ad inoltrare la richiesta ad un demone che è in attesa sulla macchina remota. Il demone ascolta la richiesta del nostro processo, esegue quello che deve eseguire, e ritorna i risultati indietro per la rete.

Realizzazione

Ogni procedura, per essere chiamata, deve avere il suddetto stub.

Il demone di cui sopra, quando riceve la richiesta di esecuzione di una procedura, deve innanzitutto controllare se questa procedura, effettivamente, c'è. Lo scambio di messaggio per la rete è gestito in automatico dal SO, il programmatore non deve preoccuparsene.

Da notare che la RPC non serve per trasmettere messaggi. Al contrario, sono i messaggi ad essere usati dalla RPC. La RPC non manda dati ad un processo remoto, al fine di mettersi in comunicazione con quel processo. No: manda solo i parametri che servono, e attende dei risultati. Per ottenere questo risultato, usa i messaggi, ma non viceversa.

Problema: le varie macchine possonon avere un modo diverso di rappresentare i dati. Pensiamo a little-endian, big-endian etc. Ecco allora che si è inventato lo standard XDR per trasmettere i dati in un modo univoco per la rete. Poi ci pensa la macchina locale a convertire da XDR nel formato locale.

Certo, se le due macchine in rete usano la stessa rappresentazione dei dati, convertira da e verso XDR è uno spreco di tempo. Però, non si sa mai chi ci sarà di là ad ascoltare, quindi meglio farlo sempre.

Un altro problema è: quante volte viene eseguita la mia procedura, remotamente? Ricordiamoci infatti che si passa attraverso una rete, che è inaffidabile, può non vedere pacchetti, può vederseli arrivare doppi ed altre stranezze.

Qui, dipende dalla politica di implementazione:

  • al più 1 volta: se non ci sono errori, ok, altrimenti pace, non ritorna risultati
  • esattamente una volta: se c'è un errore, ripeto. Se arriva 2 volte la stessa richiesta, la seconda va scartata. Si vede subito che è più compless della prima.

Un'applicazione delle RPC è il FS distribuito, in cui le chiamate per accedere ai files vengono inviate in modo trasparente (sigh) a un qualche demone RPC, che poi risponderà bla bla bla.

RMI

RMI = Remote Method Invocation, ed è una tecnologia Java. In sostanza, si estende il concetto di procedura remota alla tecnologia ad oggetti.

Un oggetto è una struttura contentente dati e metodi, ovvero procedure che lavorano su quei dati. Le RMI mi permettono di interagire con oggetti posti su macchine virtuali Java (JVM) remote.

Per JVM remota si intende una qualsiasi JVM che NON sia quella del mio processo. Posso eg avere 2 JVM sulla stessa macchina, ma l'una rispetto all'altra è sempre remota.

Il cliento ha lo stub, il server lo skeleton, e l'ambiente Java fa tutto lui in modo TRASPARENTE al programmatore.

Torna alla pagina di Sistemi Operativi