Il sistema operativo per gestire efficientemente l’I/O può servirsi di una strutturazione in livelli. I livelli più bassi servono per mascherare le specifiche hardware dei dispositivi mentre quelli superiori servono per fornire un interfaccia comune agli utenti (device-independent). Il concetto chiave è proprio l’ indipendenza del dispositivo. Dovrebbe essere possibile scrivere programmi che lavorino indifferentemente con un hard disk o con un floppy senza modificare il codice. Innanzitutto per ottenere l’indipendenza del dispositivo devo avere uniform naming. Il nome di un dispositivo o di un file deve essere una stringa e non dipendere dal nome del dispositivo. In UNIX file e dispositivi sono gestiti nello stesso modo: i floppy e gli altri dispostivi sono montati ed il SO maschera il fatto che sono “estranei” . In Windows questo non avviene e devo specificare dove si trovano (a:/ ). Un’altra funzione importante del SO è l’error handling. La rilevazione di errori deve essere gestito il più vicino all’ hardware possibile. Se il controller del dispositivo scopre errore, richiede di nuovo il dato. Solo se il problema non può essere risolto dai livelli più bassi, i livelli più alti ne vengono informati (ad es. qualcuno ha tolto il dischetto). Ultimo ma non secondario aspetto: il SO deve gestire la virtualizzazione delle periferiche, fornendo quindi uno stesso dispositivo per più utenti, come se ci fossero più copie della stessa periferica (per esempio permettere a più utenti di usare una sola stampante). Alcune periferiche possono essere virualizzate (dischi, stampante, rete) altre no (schermo, tastiera) ecc… Per quanto riguarda le periferiche virtualizzate, SO si occupa di gestire i possibili conflitti tra utenti (più utenti vogliono scrivire sulla stampante o accedere ad un file). La strutturazione in livelli dell’ I/O può avere il seguente aspetto:
A livello più basso ci sono gli interrupt che servono per segnalare via hardware al SO il verificarsi di determinati eventi (es un blocco di dati è pronto). Tutto il codice che dipende dal dispositivo nel livello device driver. I controller hanno dei registri che sono usati per trasferire dati/comandi. Il driver è quella parte del SO che conosce quanti e quali registri ci sono nel controller. Il driver conosce inoltre i comandi da usare per il dispositivo e controlla che siano eseguiti correttamente. Lui solo conosce le caratteristiche hardware della periferica, ad esempio quanti settori, cilindri, testine, ecc. ci sono nel disco. Il compito di un driver è di accettare richieste astratte provenienti dal device-independent software e di controllare che queste siano eseguite. Una richiesta tipica è ad es: “leggi il blocco n”. Il driver si attiva per leggere da disco, se è occupato a fare un’altra richiesta, quest’ultima viene messa in coda. Se è pronta prende la richiesta e da astratta viene tradotta in richiesta concreta determinando quale testina usare e quando. Le funzioni base fornite dal livello Device independent OS software permettono al SO di eseguire le operazioni I/O che sono comuni a tutti i dispositivi e di fornire un’interfaccia comune all’user-level software. Questo livello può essere suddiviso in altri sottolivelli:
Naming e Protezione: Questo livello si occupa del gestire il mapping tra i nomi simbolici dei driver (LPT1, A:, es.. ) ed i driver a cui si riferiscono. La Protection serve per prevenire accessi indesiderati ai dispositivi (errori, intrusioni). In MS-DOS si poteva fare tutto, non c’era protezione.
Device-independent block-size: i dischi possono avere differenti sector size. Questo livello deve mascherare questa differenza, trattando i blocchi in blocchi logici di dimensioni fissate e poi occupandosi di gestire le differenti dimensioni dei dispositivi (sia per blocchi che per stream di caratteri).
Buffering: livello dedicato a gestire letture successive di grandi blocchi di memoria e a fornire dati tutti insieme. Per lo stream di caratteri, ad esempio, un utente scrive troppo veloce sulla tastiera e non riuscirebbe a gestire l’input., senza un buffer.
Allocation: Allocare e rilasciare i dispositivi. Dispositivi possono essere usati da uno o più utenti. Questo livello si occupa dello scambio di “proprietario” dei dispositivi
Error handling: Abbiamo visto in precedenza l’error handling gestito dal device depende level. Quando il livello più basso non riesce a gestire l’errore il livello device-independent software ne viene informato. L’ errore viene quindi gestito in modo indipendente dal dispositivo (informando il processo che aveva fatto la richiesta oppure visualizza un messaggio di errore).
Infine il livello User-Space I/O Software mette a disposizione dei programmatori delle librerie di funzioni di sistema operativo che permettono, tra l’altro, di usare i dispositivi connessi al PC. Una chiamata classica è (linguaggio C): count=write(fd, buffer,nbytes);
Tutto quanto riportato in questa pagina è a puro scopo informativo personale. Se non ti trovi in accordo con quanto riportato nella pagina, vuoi fare delle precisazioni, vuoi fare delle aggiunte o hai delle proposte e dei consigli da dare, puoi farlo mandando un email. Ogni indicazione è fondamentale per la continua crescita del sito.