Articolo pubblicato sul n. 90 di MCmicrocomputer (Edizioni Technimedia Srl - Roma) nel novembre 1989

MCmicrocomputer


Amighevole:
ADPnetwork: una rete per Amiga
seconda puntata

di Andrea de Prisco

Dopo la propedeutica introduzione su ADPnetwork fatta lo scorso mese, in questa seconda puntata analizzeremo piu' dettagliatamente il funzionamento dei processi piu' importanti e mostreremo lo schema di collegamento delle macchine, attualmente effettuato per mezzo della porta seriale.Copertina del numero di MCmicrocomputer contenente l'articolo

Bisogna dire una cosa: se Amiga non fosse stato un computer multitasking, realizzare una rete come ADPnetwork sarebbe stato davvero difficile. Proprio ieri mattina, ad esempio, ho iniziato a studiare la struttura di un potenziale software di gestione di un microcontroller capace di gestire in parallelismo simulato un certo numero di eventi assolutamente asincroni (quindi indipendenti) tra loro. Nonostante alla fine abbia avuto io la meglio, la mia mente s'era cosi' abituata a ragionare in termini di processi paralleli (e indipendenti anch'essi) che le maledizioni inoltrate al quel povero microcontroller ormai nessuno riusciva piu' a contarle. Fortunatamente non dovremo aspettare ancora molto (almeno me lo auguro) prima di vedere i primi processori dotati di linguaggio macchina multitasking, anche se realizzato a semplici colpi di time sharing.

Provate ad immaginare, ad esempio, cosa significa per un singolo programma controllare eventi differenti senza mai effettuare attese attive a scapito di altre operazioni da portare a termine: ad esempio un bel programma che riceve flussi di dati da due canali, elaborarando gli eventuali dati provenienti dal canale 1 e, simultaneamente, redirigere l'input del canale 2 su un terzo canale d'uscita. Puo' succedere ad esempio che mentre dal canale 1 arrivano dati da elaborare sul canale 2 arrivino dati da redirigere sul canale 3 e tutte le operazioni debbano essere compiute molto velocemente onde evitare perdite di dati causate da riempimenti di buffer.

Certo, in informatica, tutto quello che si puo ben dire si puo' ben fare, ma volete mettere una soluzione al problema realizzata con due o piu' processi cooperanti quanto e' piu' elegante e raffinata di una soluzione monotask capace di andare avanti solo ed esclusivamente a colpi di interrupt e variabili globali ? Fine dello sfogo.

 

Riassunto della puntata precedente

 

ADPnetwork, lo ripetiamo per chi si fosse sintonizzato solo ora, adotta uno schema di funzionamento "circolare" in cui ogni macchina ha un nodo precedente, dal quale riceve il flusso dei dati, e uno successivo al quale trasmette, o ritrasmette, dati. Ogni macchina analizzera' i dati in arrivo dalla rete e dovra' essere in grado di riconoscere messaggi per se' da inoltrare agli opportuni server, oppure da rimettere in circolo non riconoscendosi come destinatario. In questo modo e' sia possibile che qualsiasi macchina dialoghi con qualsiasi altra macchina della rete, sia che in ogni istante piu' macchine effettuino operazioni sulla rete. Facendo un rapido esempio, se colleghiamo (figura 1) quattro macchine in rete attraverso ADPnetwork (la 1 con la 2, la 2 con la 3, la 3 con la 4 e quest'ultima con la 1) la macchina 2 per dialogare con la 4 passera' attraverso la 3 cosi' come quest'ultima per "parlare" con la 2 passera' attraverso la 4 e la 1. Analogamente e' possibile che CONTEMPORANEAMENTE la macchina 1 esegua una operazione sulla 2 e che la 3 esegua una qualsiasi altra operazione sulla macchina 4. Questo grazie al fatto che la struttura di comunicazione e' solo apparentemente condivisa da tutte le macchine: in realta' ogni nodo e' banalmente proprietario del collegamento fisico con la macchina successiva, tutto qui.

L'attuale release funzionante di ADPnetwork, la 3.0, permette a qualsiasi processo in esecuzione su qualunque macchina di inviare messaggi a qualsiasi altro processo in esecuzione su qualsivoglia altra macchina collegata alla rete. Ogni messaggio puo' essere di lunghezza arbitraria e per inoltrarlo via rete il processo mittente dovra' naturalmente specificare il nodo destinatario, la porta mttb esistente su quel nodo (creata cioe' dal processo destinatario) e consegnare il messaggio al software di rete. Sara' poi questo che, impacchettandolo opportunamente in frame di rete ed utilizzando l'interfaccia d'uscita verso la macchina "successiva" fara' in modo (naturalmente con la complicita' di tutti i processi di rete di tutte le macchine "attraversate") che il messaggio giunga a destinazione e sulla giusta porta.

Se una macchina decide di uscire dalla rete, basta che sconnetta il suo ingresso e la sua uscita e li colleghi tra di loro: in questo caso si ripristina automaticamente il collegamento circolare e tutte le rimanenti macchine possono continuare ad adoperare la rete.

 

Packer e Spacker

 

Sempre lo scorso mese vi ho anticipato che i due processi Packer e Spacker del Software di Rete (SDR), front-end verso AmigaDOS, si preoccupano rispettivamente di formare i frame di rete da spedire e di ricostruire i messaggi in arrivo man mano che giungono i vari frame da altre macchine. E' ovvio inoltre che impacchettamento e spacchettamento dei messaggi deve essere una coppia di funzioni non visibile ai processi AmigaDOS, ai quali importa solo di spedire un messaggio ad una derteminata macchina e riceverne da altre. Oltre a questo il processo Spacker deve essere in grado di mantenere piu' liste degli arrivi, dal momento che possono arrivare piu' richieste da piu' macchine i cui frame, come detto, non sono regolamentati da un ordine di arrivo identico a quello delle rispettive partenze. I frame di rete viaggiano infatti in maniera indipendente l'uno dall'altro e, dato che ogni macchina e' autorizzata ad annullare frame di transito contenenti errori di trasmissione e ad inserire tra un frame ed un altro in transito anche propri frame per altre macchine, capirete bene che la conquista dell'arrivo per questi sara' quantomeno faticata. Pensate ad esempio ad una rete di trasporti merci basata su ferrovia e navigazione (ad esempio un bel collegamento con le isole). Dalle stazioni di partenza vengono formati vari convogli per le relative destinazioni, spezzati pero' in piu' parti quando si tratta di attraversare tragitti marini (un intero treno, per lungo, non entra in una nave...). Immaginate inoltre (per rendere l'esempio piu' vicino al traffico su rete) che per motivi di ottimizzazione ogni volta che c'e' da caricare una nave di carri ferroviari si cerchi sempre di riempire al massimo ogni nave, prelevando carri anche da convogli diversi. Ovviamente, pero', a destinazione i convogli dovranno arrivare sempre e comunque con tutti i vagoni al loro posto e nel medesimo ordine della partenza, dunque le stazioni d'arrivo dovranno raccogliere man mano i vagoni che arrivono e ricomporre i convogli prima di strillare "in arrivo sul terzo binario...".

E, gia'! un solo binario non basta proprio: puo' sucedere che arrivino prima un po' di pezzi del treno 208, poi tre vagoni del treno 665, poi ancora del treno 208, poi un carro del 256...

Spacker funziona proprio allo stesso modo. Arrivato un qualsiasi frame, la prima operazione che compie e' vedere se gia' ha inizializzato una lista d'arrivo relativa a quel determinato messaggio. L'identificazione unica del messaggio e' riportata all'interno di ogni frame: basta guardare il campo mittente e il campo MsgID, incrementato dal mittente stesso ogni nuova spedizione. Tale informazione e' presente anche nelle liste d'attesa dello spacker. O, meglio, e' presente se la lista era gia' stata istanziata precedentemente oppure viene inizializzata se si tratta del primo frame relativo a quel messaggio. Altre informazioni utili che possiamo prendere dal primo frame arrivato sono la lunghezza effettiva del messaggio originale (rapportato all'esempio dei treni, la lunghezza del convoglio al momento della partenza) in modo da allocare una giusta quantita' memoria per ricostruire il messaggio, e la posizione relativa del frame arrivato all'interno del messaggio originario. Allocata, dunque, la giusta quantita' di memoria, il corpo del frame arrivato viene ricopiato nella giusta posizione all'interno del messaggio in arrivo. Relativamente a quella lista d'attesa e' incrementato della giusta "dose" il campo "Arrived" che contiene costantemente la quantita' di byte effettivamente arrivati a destinazione. Non appena tale campo raggiunge l'effettiva lunghezza del messaggio (e puo' succedere anche subito, dopo il primo frame, se esso viaggiava effettivamente su un solo pacchetto) il messaggio e' considerato arrivato in toto, inoltrato all'effettiva porta destinataria creata da un processo in esecuzione su quella macchina, e viene immediatamente deallocata la memoria occupata per la ricostruzione.

 

Sender e Dispatcher

 

Il processo Sender, del quale data la sua estrema semplicita' non e' stato preparato un diagramma di flusso, si occupa di effettuare le spedizioni di frame. Frame provenienti dalla stessa macchina, quindi contenenti richieste o risposte da recapitare ad altri nodi appositamente "impacchettati" dal processo Packer, oppure frame di transito scartati dal processo Dispatcher che non li ha riconisciuti come propri. Attualmente i frame in via di spedizione vengono accodati tutti sulla stessa porta, sia quelli che provengono dal Dispatcher che quelli provenienti dal Packer. In altre parole non si e' voluto stabilire una priorita' tra frame in transito e frame in partenza ed effettivamente chi dei due processi esegue per primo la Send verra' per primo servito dal Sender.

Naturalmente nulla vieta di aggiungere una o piu' porte al processo Sender in modo da poter scegliere di volta in volta cosa inviare per prima, secondo uno schema di priorita', volendo, variabile dinamicamente. Ad esempio si potrebbero favorire i frame in transito, dal momento che compongono una operazione iniziata sicuramente prima dell'operazione in corso sulla nostra macchina. Oppure si potrebbe stabilire di prendere un frame per porta e cosi' intervallare frame in transito con frame in partenza senza mai favorire nessuna opportunita'. Ancora, potremmo stabilire la priorita' delle singole macchine in rete in modo da favorire determinate postazioni che eseguono lavori piu' urgenti di altre.

Queste sono comunque tutte scelte che protremo valutare meglio solo quando saremo prossimi ad una release "abbastanza definitiva" di ADPnetwork (il progetto, sebbene funzionante, e' in continuo sviluppo per ottimizzare quanto piu' e' possibile tutto l'ottimizzabile), testando cosi' il comportamento in rete dei prodotti software di maggior interesse (che, fortunatamente per gli utenti e sfortunatamente per noi, non sono affatto pochi...).

Per quel che riguarda il processo Dispatcher, dando uno sguardo al suo diagramma di flusso, possiamo notare come sia anch'esso concettualmente molto semplice. Il suo lavoro e' quello di aspettare sul canale di ingresso della rete l'arrivo di un frame. Arrivato il frame, la prima operazione che compie e' controllare se il mittente e' uguale al nome dello stesso nodo su cui gira il processo. In caso affermativo, infatti, cio' significa semplicemente che il frame ha fatto tutto il giro della struttura ad anello (passando per tutte le macchine in rete) con conseguente deduzione che il destinatario del messaggio in transito non esiste. Quando si verifica una situazione del genere ovviamente l'SDR invia un apposito messaggio d'errore al processo (in esecuzione sulla stessa macchina) che aveva richiesto un'operazione su una macchina inesistente.

Se invece il mittente del messaggio e' diverso dal nome del nodo in questione, il secondo test che effettua il Dispatcher e' naturalmente sul destinatario. In questo modo smista i frame per altre macchine direttamente al Sender e i frame per quel nodo al processo Spacker che provvedera' a ricostruire il messaggio originario man mano che arrivano i vari frame.

 

Gli altri Processi

 

ADPnetwork, come gia' detto piu' volte lo scorso mese, non si ferma certo qui. Esistono infatti altri due processi di importanza strategica che rendono la rete sufficientemente fault tolerant. La descrizione fatta finora praticamente riguarda la release 2.0 che al minimo errore di trasmissione dava forfait costringendo ad abortire le operazioni in esecuzione "coinvolte nell'intoppo".

Il processo Packer, in realta', teminata la fase di impacchettamento del messaggio non butta via quest'ultimo ma lo passa cosi' com'e' al processo Replay. Contemporaneamente avvisa un altro processo, Timer, di avvertire il processo Replay dopo un prefissato intervallo di tempo. Ricevuto tale segnale di sveglia dal Timer, il processo Replay controlla quali frame sono giunti a destinazione e quali no, provvedendo a rispedire quelli "persi per strada". Ma come fa il processo Replay a stabilire quali frame sono arrivati e quali no ?

Semplice: il Dispatcher della macchina destinataria, man mano che riceve i frame per quel nodo, provvede a reinviare un minipacchetto di ACK per ogni frame passato allo Spacker. Replay tiene nota degli ACK ricevuti e, conseguentemente, di quelli non ricevuti potendo cosi' "dedurre" cosa manca al destinatario. Naturalmente se allo scadere del timeout tutti gli ACK erano tornati indietro, Replay non fa assolutamente nulla, se non deallocare la zona di memoria contenente copia del messaggio spedito. Bello, no ?

 

Utilizziamo la porta seriale

 

La figura 1 mostra, come detto, lo schema di collegamento circolare di ADPnetwork. Tale collegamento e' dettato dallo stesso Software di Rete che lavora "sapendo" che le macchine sono collegate in quella maniera. Tutto cio', credo, sia fin troppo chiaro e gia' da un pezzo. Al fine di testare il corretto funzionamento dei vari processi in esecuzione sulle macchine, a scopo puramente sperimentale, sin dai primi passi e' stata utilizzata l'interfaccia seriale presente su ogni macchina. Per essere piu' precisi, ogni Amiga dispone di due interfacce separate, ed utilizzabili separatamente, una di uscita ed una di ingresso. La prima la collegheremo alla macchina successiva, l'altra alla macchina precedente.

In questa situazione, viaggiando ai canonici 19200 bps, la rete funziona bene anche se molto lentamente per operazioni impegnative. Diciamo che la velocita' ottenuta e' circa un quarto della velocita' di un'unita' per microfloppy presente su ogni Amiga. Dunque se dobbiamo trasferire grossi file, andiamoci pure a prendere un bel caffe', mentre per operazioni piu' rapide, se non siamo troppo abituati a velocita' di altri sistemi possiamo anche chiudere un occhio (...una narice e un orecchio) e accontentarci della sola rete software.

Detto questo, onde evitare di realizzare cavi di forma stellare per connettere piu' macchine tra di loro (ognuna delle quali, come si sa, dotata di connettore unico della seriale) e' stato ideato lo schema di collegamento di figura 3 utilizzante su ogni Amiga un banale partitore di ingresso e uscita, collegando le macchine intermedie con normali cavi seriali e dotando le macchine all'estremita' di un opportuno terminatore. Da notare che, pur assomigliando ad un collegamento su bus, la comunicazione avviene attraverso la struttura ad anello di figura 1 e cio' puo' essere facilmente verificato seguendo, sempre in figura 3, le frecce presenti sui collegamenti elettrici che indicano la direzione del flusso di dati. Volendo aggiungere una nuova macchina, bastera' utilizzare un nuovo partitore e un nuovo cavo seriale standard ed effettuare l'inserimento in qualsiasi punto: la struttura ad anello e' sempre rispettata.

 

Conclusioni

 

Nel cedere (momentaneamente...) la parola a Marco Ciuchini e Andrea Suatoni che a partire dal prossimo numero ci "canteranno" del loro Net-Handler per la rete, voglio spendere due parole sul futuro di ADPnetwork.

L'utilizzazione di tale Software di Rete attraverso la porta seriale e' effettivamente troppo limitativo. E se qualcuno pensa di far viaggiare la stessa a velocita' piu' elevate (in teoria potrebbe andare anche ad oltre 100 Kbuad) sappia che anche ipotizzando di riuscire a raggiungere tali valori di velocita' non possiamo utilizzare gli Amiga collegati in rete SOLO per la rete. Le singole postazioni devono infatti continuare a funzionare come normali Amiga su cui caricare, assieme all'SDR anche le applicazioni per lavorare.

Ne', evidentemente, alla Commodore pensavano di utilizzare la seriale per scopi diversi dal semplice interfacciamento con periferiche, come invece succede nei Macintosh capaci di far viaggiare (senza battere ciglio) la loro seriale a oltre 200 Kbaud, implementando su di essa (sin dalla nascita del Mac) la rete AppleTalk.

L'alternativa e' naturalmente unica, ed e' possibile (ancora una volta) grazie alla struttura particolamente aperta di Amiga: realizzare una scheda hardware da attaccare agli Amiga in modo da ottenere il duplice vantaggio di aumentare la velocita' di trasferimento tra le macchine (utilizzando una forma di interfacciamento piu' evoluta) e demandare all'elettronica il riconoscimento dei frame. In questa maniera le macchine non interessate ad un trasferimento ma funzionanti, in quel momento, solo come ponte per la comunicazione non vengono affatto rallentate come invece accade utilizzando la seriale e le risorse interne di calcolo. Comunque di questo e di altri aspetti del futuro di ADPnetwork avremo modo di parlarne piu' in la. Arrivederci...



Impaginato originale...


Clicca per ingrandire... Clicca per ingrandire...
Clicca per ingrandire... Clicca per ingrandire...
Clicca per ingrandire... Clicca per ingrandire...

Articolo pubblicato su www.digiTANTO.it - per ulteriori informazioni clicca qui