Port ] [ Debian GNU/Hurd ] [ Notizie ] [ Configurazione ] [ CD di Hurd ] [ Documentazione ] [ Sviluppo ] [ Contatti ]

Debian GNU/Hurd

Traduttori

Il concetto

Per approfondire l'argomento traduttori si usa come esempio i normali filesystem, un filesystem è supporto di memorizzazione con un albero gerarchico di directory e file. Per accedere alle directory e ai file si usa una speciale stringa di caratteri, il percorso. Inoltre esistono link simbolici per rimandare a uno stesso file da diversi punti dell'albero delle directory e hard link per dare a uno stesso file più nomi. Ci sono dei file speciali detti device per comunicare con i driver per il kernel dei dispositivi hardware e ci sono i mount point per includere altri supporti di memorizzazione nell'albero delle directory. Infine esistono anche altri strani oggetti come le fifo.

Sebbene questi oggetti siano molto diversi condividono alcune proprietà comuni, ad esempio hanno un proprietario, sono associati a un gruppo e hanno dei diritti di accesso (permessi); tutte queste informazioni sono scritte negli inode. Un'altra cosa fondamentale: ogni oggetto è associato a esattamente un inode (gli hard link sono in qualche modo speciali dato che condividono lo stesso inode). In alcuni casi nell'inode sono memorizzate anche informazioni differenti, per esempio possono contenere la destinazione di un link simbolico.

Comunque queste funzionalità comuni di solito non sono sfruttate nelle implementazioni e sono rimandandate alla loro interfaccia di programmazione che è standard. Infatti si può accedere a tutti gli inode usando le chiamate standard POSIX come read() e write(). Per esempio, per aggiungere un nuovo tipo di oggetto (un nuovo tipo di link) a un kernel unix monolitico si deve modificare il codice per ogni filesystem.

In Hurd le cose funzionano in modo diverso. Sebbene nell'Hurd uno specifico servente per il filesystem possa sfruttare le proprietà speciali dei tipi di oggetto standard come i link (per esempio nel filesystem ext2 i fast link) ha anche una interfaccia generica che permette di aggiungere delle funzionalità senza modificare il codice esistente.

Il trucco consiste nel permettere l'inserimento di un programma fra il reale contenuto di un file e l'utente che accede a quel file. Un programma di questo tipo è chiamato traduttore dato che è capace di elaborare le richieste in arrivo in molti modi diversi. In altre parole un traduttore è un servente Hurd che fornisce l'interfaccia verso il filesystem sottostante.

I traduttori hanno delle proprietà molto interessanti. Dal punto di vista del kernel i traduttori sono dei normali processi dell'utente, questo significa che i tradutori possono essere eseguiti da qualsiasi utente, che non sono necessari i privilegi dell'utente root per installare o modificare un traduttore e che invece sono sufficienti i giusti permessi di accesso all'inode su cui è collegato il traduttore. Molti traduttori non richiedono un reale file per funzionare, infatti possono fornire informazioni per proprio conto, questo perché le informazioni sui traduttori sono memorizzate nell'inode.

I traduttori si occupano di servire tutte le operazioni sul filesystem che convolgono gli inode a cui sono collegati. Poiché non sono limitati dal normale insieme di oggetti (file device, link, ecc.) sono liberi di restituire qualsiasi cosa che ha senso al programmatore. Si può immaginare un traduttore che si comporta come una directory quando ci si accede con cd o ls e che allo stesso tempo si comporta come un file quando ci si accede con cat.

Esempi

Mount point

Un mount point può essere visto come un inode su cui è attaccato uno speciale traduttore, il cui scopo è tradurre le operazioni sul filesystem del mount point su un altro supporto di memorizzazione, per esempio un'altra partizione.

Sia chiaro, qui è descritto come sono implementati i filesystem sotto Hurd. Un filesystem è un traduttore. Questo traduttore prende come argomento un supporto di memorizzazione ed è capace di servire in modo trasparente tutte le operazioni sul filesystem.

File device

Ci sono file device molto diversi che nei sistemi con un kernel monolitico sono tutti forniti dal kernel stesso. In Hurd tutti i file device sono forniti da dei traduttori. Un traduttore può fornire il supporto per parecchi file device simili, per esempio tutte le partizioni del disco fisso. In questo modo il numero effettivo di traduttori necessari è piuttosto piccolo, comunque si noti che quando si accede a ogni file device viene avviato un task del traduttore separato. Poiché Hurd è pesantemente multi-threaded, questo risulta essere particolarmente economico.

Quando è coinvolto l'hardware di solito un traduttore inizia a comunicare con il kernel per avere i dati dall'hardware, invece se non è necessario accedere all'hardware allora il kernel non viene coinvolto. Per esempio /dev/zero non richiede l'accesso all'hardware e quindi può essere implemento completamente in spazio utente.

Link simbolici

Anche un link simbolico può essere visto come un traduttore. L'accesso a un link simbolico fa partire un traduttore che inoltra la richiesta al filesystem che contiene il file a cui punta il link.

Per migliorare le prestazioni i filesystem supportano nativamente i link simbolici e quindi possono trarre vantaggio da questa funzionalità implementando i link simbolici in modo ottimale. Internamente l'accesso ai link simbolici non fa partire un nuovo processo traduttore. Comunque per l'utente può sembrare che sia coinvolto un traduttore passivo (si veda più sotto per una spiegazione di che cosa è un traduttore passivo).

Dato che fa parte dell'Hurd anche un traduttore per i link simbolici, qualsiasi servente per filesystem che ha il supporto per i traduttori automaticamente ha il supporto per i link simbolici (per i link statici, per i file device, ecc.)! Questo significa che si può avere un filesystem funzionante molto rapidamente e aggiungere il supporto per i link simbolici e altre funzionalità successivamente.

Taduttori passivi e taduttori attivi

Esistono due tipi di traduttori: passivi e attivi. Sono due cose molto diverse, attenzione a non fare confusione, ma sono anche strettamente legate l'una all'altra.

Traduttori attivi

Come già detto un traduttore attivo è un processo traduttore in esecuzione. Si possono attivare e rimuovere i traduttori attivi con il comando settrans -a. L'opzione -a è necessaria per indicare a settrans che si vuole modificare un traduttore attivo.

Il comando settrans accetta tre tipi di argomento. Per prima cosa si possono impostare le opzioni del comando settrans stesso, come -a necessaria modificare il traduttore attivo. Poi si specifica l'inode che si intende modificare, ricordarsi che un traduttore è sempre associato con un inode dell'albero delle directory e che si può modificare un solo inode alla volta. Se non si specificano altri argomenti settrans tenterà di rimuove un traduttore esistente. La forza di questi tentativi dipende dalle opzioni specificate (se il traduttore è in uso da parte di un processo si riceverà il messaggio di errore "device or resource busy" a meno che non si forzi la sua fine).

Se si specificano altri argomenti, vengono interpretati come la riga di comando per eseguire il traduttore. Questo significa che l'argomanto successivo è il nome del file eseguibile del traduttore. Ulteriori argomenti sono le opzioni del traduttore e non del comando settans.

Per esempio per montare una partizione ext2fs si può eseguire settrans -a -c /mnt /hurd/ext2fs /dev/hd2s5. L'opzione -c crea il mount point se questo ancora non esiste, non è necessario che sia una directory. Per smontare si può usare settrans -a /mnt.

Traduttori passivi

Un traduttore passivo viene impostato e modificato con la stessa sintassi di un traduttore attivo (tralasciando l'opzione -a) tutto quello detto precedentemente è valido anche per i traduttori passivi. Comunque c'è una differenza: i traduttori passivi non sono stati ancora avviati.

Questo ha senso perché è il comportamento che normalmente vuole l'utente, non si vogliono montare le partizioni fino a quando non si accede realmente ai file presenti su quelle partizioni, non si vuole attivare la rete fino a quando non c'è del traffico e così via.

Invece la prima volta che si accede a un traduttore passivo viene automaticamente letto dall'inode e un traduttore attivo viene avviato sopra usando la riga di comando che è memorizzato nell'inode. Questo è simile al meccanismo automount di Linux, con la differenza che non è una funzionalità aggiuntiva che deve essere impostata manualmente ma è una parte integrante del sistema. Quindi l'impostazione dei traduttori passivi rimanda l'avvio del task traduttore fino a quando non sia necessario. Nel caso che un traduttore attivo muoia per qualsiasi ragione la volta successiva che si accede all'inode il traduttore viene riavviato.

C'è un'ulteriore differenza: i traduttori attivi possono morire o perdersi. Appena il processo del traduttore attivo muore (per esempio perché si riavvia la macchina) è perso per sempre. I traduttori passivi non sono temporanei e rimangono nell'inode nonostante i riavvii fino a quando non si modificano con il programma settrans o si cancella l'inode a cui sono collegati. Questo significa che non serve tenere un file di configurazione con l'elenco dei mount point.

Infine, anche se si è impostato un traduttore passivo si può impostare un traduttore attivo differente. Solo se il tradutore è avviato automaticamente perché non c'era un altro traduttore attivo quando è stato fatto l'accesso all'inode viene considerato il traduttore passivo.

Gestione dei traduttori

Come detto precedentemente si può usare settrans per impostare e modificare i traduttori attivi e passivi. Ci sono molte opzioni per cambiare il comportamento di settrans nel caso che qualcosa vada male e per condizionare i suoi effetti. Qui sono riportati alcuni comuni usi:

Si può usare il comando showtrans per vedere se un traduttore è collegato a un inode. Purtroppo questo comando mostra solo i traduttori passivi.

Si possono cambiare le opzioni di un traduttore (per filesystem) attivo con fsysopts senza riavviarlo, è veramente molto comodo. Per esempio si può fare quello che sotto Linux è "rimontare una paritzione in sola lettura" semplicemente eseguendo fsysopts /mntpoint --readonly. Il traduttore attivo in esecuzione modificherà il proprio comportamento in base alle richieste se è possibile. fsysopts /mntpoint senza altri parametri mostra le impostazioni attuali.

Esempi

Si raccomanda di iniziare leggendo il comando /bin/mount, è solo un piccolo script dato che l'impostazione dei traduttori per i filesystem è simile al montare le partizioni, si può facilmente comprendere il concetto. Creare una immagine di un filesystem con dd if=/dev/zero of=dummy.fs bs=1024k count=8; mke2fs dummy.fs e montarlo con settrans -c dummy /hurd/ext2fs `pwd`/dummy.fs. Notare che il traduttore ancora non è partito, non c'è un processo ext2fs in esecuzione (lo si può verificare con ps Aux). Controllare che tutto sia apposto con showtrans.

Adesso digitare ls dummy, noterete un piccolo ritardo necessario all'avvio del traduttore. In futuro non ci dovrebbero essere altri ritardi per accedere a dummy, sotto Linux si potrebbe dire che è stato fatto l'automount di un filesystem di loop. Controllare con ps Aux che c'è un processo ext2fs attivo e in esecuzione. Adesso aggiungere alcuni file nella nuova directory. Provare a rendere il filesystem di sola lettura con fsysopts, i successivi tentativi di scrittura falliranno. Provare a uccidere il traduttore attivo con settrans -g.

Adesso si dovrebbe aver chiaro cosa succede, ricordarsi che questo era solo un servente, il servente Hurd ext2fs. Ci sono molti altri serventi nella directory hurd, alcuni di essi sono per i filesystem, alcuni sono necessari per le funzionalità del filesystem come i link, alcuni sono necessari per i file device, alcuni per la rete. Si immagini di montare un server FTP con settrans e di scaricare i file semplicemente con il normale comando cp o modificare il vostro sito web con emacs /ftp/homepage.my.server.org/index.html!