You are on page 1of 29

Input/Output

Il sistema operativo deve fornire un interfaccia semplice per luso dei


dispositivi di I/O, e che sia indipendente dal dispositivo.
I/O, sono periferiche, consentono allutente di interagire con il
sistema(hardisk, stampanti, ecc..).Il sistema operativo deve gestire queste
periferiche, utilizzando delle astrazioni(oggetti emulati via software), in
questo contesto ogni periferica un oggetto programmabile, con una memoria(per
salvarne lo stato). Ogni periferica ha linguaggi macchina differenti, quindi per
interfacciarci con esse utilizziamo i driver.
I dispositivi di I/O possono essere suddivisi in 2 categorie:
1. dispositivi a blocchi, i dati che vengono scambiati tra device e S.O. sono
blocchi di dimensione fissa(uno o pi). NB ogni blocco ha il suo
indirizzo. La caratteristica fondamentale di questi device che ciascun
blocco pu essere letto o scritto indipendentemente(es: hard-disk(divisi
in settori) blueray, usb)
2. dispositivi a caratteri, i dati che vengono scambiati sono flussi di
caratteri, non indirizzabile e non ha operazioni di ricerca(es:
Stampanti, mouse)

Alcuni dispositivi rimangono esclusi da questa classificazione, esistono


implementazioni ibride es: clock che non indirizza blocca n genera o accett
flussi di caratteri

Le periferiche hanno velocit diverse, quindi il


software che interagisce con le periferiche devessere
indipendente dalla velocit.

Le periferiche sono composte da due parti una meccanica e una elettronica, la


parte elettronica chiamata controller, che riceve ordini dal microprocessore e
li comunica al dispositivo, e viceversa(un chip sulla scheda madre, o una scheda
inseribile nei PCI)

Il controller pu essere
inserito o nel bus, con
uninterfaccia standard(USB,
PCI ecc), oppure sulla
periferica stessa, in questo
caso in dispositivo ha una
sola interfaccia. NB le
interfacce che collegano
dispositivo e controller sono
standardizzate e i
dispositivi vengono fatte in
modo che vadano bene con
quelle interfacce
Come agisce? Il lavoro del controller convertire flussi di bit in blocchi di
byte pronti per essere spediti.

I bus di memoria sono hanno una certa velocit, quindi non ha senso collegare
tutti i dispositivi al bus(hanno velocit differenti), solitamente si hanno pi
bus di memoria.

Solitamente abbiamo:

1. 1 bus ISA, per le periferiche pi lente, ha diversi slot


2. 1 bus PCI per le periferiche pi veloci(SCSI, USB, schede grafiche)
Per collegare pi bus utilizzo un ISA bridge, esiste anche un PCI bridge, per
permettere alla CPU di andare verso la memoria e per consentire le comunicazione
tra PCI e altri bus. Esiste anche un CACHE BUS che usato dalla CPU.

Come interagisce la CPU con i dispositivi?

Il dispositivi hanno dei registri di controllo:


1. control register, serve per inviare comandi
2. data register, serve per inviare dati
Il S.O. scrive in questi registri per comunicare con il dispositivo, inoltre,
solitamente i dispositivi hanno un buffer, su cui il sitema pu leggere o
scrivere.
Per referenziare questi registri assegniamo indirizzo univo ai registri nel
controller. Per indirizzare questi registri utilizziamo uno schema di
indirizzamento, esistono 2 alternative:
Porte di I/O, a ogni registro assegno un numero progressivo(numero di
Porta di I/O), linsieme dei numeri di porta di I/O(i numeri vengono
assegnati dal bios allavvio del sistema) forma lo spazio delle porte di
I/O(una tabella) ed protetto in modo che i programmi utente non possano
accedervi. Il problema ora come distinguere il caso in cui voglia
indirizzare un registro di controllo oppure la
memoria
Il numero tiene anche conto in quale controller si
trovano i registri
Dal punto di vista hardware abbiamo:

La mode line specifica se lindirizzo nella date line si riferisce alla memoria
o a porte di I/O, per scrivere in mode line usiamo:
1. IN/OUT(per le porte di I/O)
2. IN/MOV(per la memoria)

In alternativa, abbiamo lI/O mappato direttamente in memoria(unico spazio


degli indirizzi)

Dal punto di vista hardware abbiamo soltanto 2 linee che


escono dalla CPU poich non dobbiamo specificare da dove
leggere. A ogni registro assegnato un indirizzo assoluto
di memoria. NB i controller sanno che range di indirizzi
devono gestire

Confronto implementazioni(VANTAGGI e SVANTAGGI)

Porte di I/O I/O mappato in memoria


Non ho necessit di istruzioni
speciali, il ch semplifica la
scrittura dei driver.
Non necessit di meccanismi di
protezione per evitare che i processi
utente eseguano l I/O, il S.O deve
evitare di mettere lo spazio degli
indirizzi assegnato ai registri di
controllo, allinterno dello spazio
degli indirizzi virtuale di qualche
utente, normalmente ci che si fa
assegnare pagine diverse(sullo spazio
degli indirizzi) a ogni controller, in
modo da facilitare: protezione e
condivisione di dispositivi
I registri di controllo possono essere
referenziati dalle stesse istruzioni
che possono refereziare la memoria
es:
TEST: TEST PORT_4
BEQ READY
BRANCH LOOP
READY:
Linterazione con la cache potrebbe
essere dannosa, siccome lo spazio degli
indirizzi uno solo(non so se leggo
dalla memoria o da I/O), ci che
succede che se un dato di un registro
di controllo viene portato in cache,
nelle iterazioni successive il dato
verr letto dalla cache, ma i dati nei
registri di controllo cambiano in
continuazione, questo causa errori, per
evitare questo problema potrei:
disabilitare la cache in maniera
selettiva(hardware ancora pi
complicato).
Ogni volta che passo un indirizzo in
AL, le periferiche devono controllare
se gli appartiene(se si rispondiamo),
per fare questo devono vedere
lindirizzo il problema che se
abbiamo due bus separati lI/O non vede
subito la richiesta(ILLUSTRAZIONE 1)
soluzioni:
1. invio lindirizzo/i al bus di
memoria, se dopo k clock non
risponde lo mando sugli altri
bus(hardware molto complesso)
2. mettere un filtro sul bus di
memoria, in modo che intercetti
gli indirizzi di I/O(problema
lI/O pi lento della memoria)
3. implementare un chip sul BRIDGE
PCI, che funge da filtro per gli
indirizzi di non memoria, al
momento dellavvio il chip
caricato con indirizzi che
contengono indirizzi di registri
di controllo, quando arriva un
indirizzo si fa un check e se
vero si inoltra al bus PCI

Illustrazione 1
DMA

Come fa una periferica a comunicare con il processore? Quando la CPU richiede un


comando, la CPU pu(per verificare la fine):
Ispezionare continuamente la periferica, ma non molto efficiente
Interrupt, invia un segnale sulla linea del bus

Analizziamo come funziona questo meccanismo:

Abbiamo un interrupt controller su un chip della scheda madre che specifica cosa
fare dopo un interruzione; Ogni dispositivo dotato di un interrupt
handler(implementato tramite interrupt Vector). Il segnale cos lanciato
intercettato dal controller, se non ci sono altri interrupt in attesa lo
processa immediamente; se arrivassero 2 interrupt contemporaneamente uno con
priorit pi alta, si processa prima quello con priorit pi alta, laltro
dispositivo sospeso. Per gestire linterrupt il controller assegna un numero
sulle numero alle linee di indirizzi il cui dispositivo vuole attenzione e
sottopone un segnale per interrompere la CPU. Il numero sulla linea degli
indirizzi usato come un indice allinterno del vettore degli
interrupt(interrupt handler) per prelevare un nuovo contatore di programma(punta
alla procedura di gestione degli interrupt).

Per ovviare a questi problemi si utilizza il DMA

Come fa la CPU ad accedere ai controller dei dispositivi? La cpu potrebbe


dialogare con ogni singolo dispositivo trasferndo 1 byte alla volta ma
dispendioso; Il DMA ha accesso al bus di sistema indipendentemente dalla CPU,
esso ha alcuni registri:
1. Address, registro degli indirizzi
2. Count, registro di conteggio dei byte
3. Control, specificano le porte di I/O da usare, la direzione del
trasferimento(leggere dal dispositivo, o scrivere sul dispositivo), e
lunit di trasferimento(un byte 4 byte un bit un settore ecc)
Come avviene una lettura da disco senza DMA? , il controller legge serialmente
da disco uno o pi settori, bit per bit, finch lintero blocco non nel
buffer, a questo punto verifichiamo il codice di controllo(per verificare che
non ci siano stati errori),il controller provoca un interrupt.
Con il DMA funziona cos:
1. La CPU programma il controller DMA impostando i suoi registri in modo che
conosca che cosa trasferire e dove(Invia anche un comando al controller
del disco chiedendogli di rileggere i dati dal disco nel suo buffer
interno e di verificare il codice di controllo)
2. il controller DMA inizia il trasferimento inviando sul bus una richiesta
di lettura al controller del disco, essa si presenta come una normale
richiesta, lindirizzo su cui scrivere(o sul DMA o in memoria) sulla
linea degli indirizzi, cos quando il controller del disco preleva la
parola successiva dal buffer del disco sa dove scriverla
3. Loperazione di scrittura in memoria un altro ciclo di bus standard
4. Quando la lettura terminate il controller del disco invia un interrupt a
l DMA
5. Il controller DMA incrementa lindirizzo di memoria da usare e diminuisce
il count, se count=0 la DMA manda un interrupt al disco altrimenti
ripetiamo 2-3-4
6. il SO ha gi i dati in memoria

Il DMA invia la richiesta di lettura al controller del disco(proprio come


farebbe la CPU), essa decide quali dispositivi servire(potrebbero esserci pi
richieste di lettura) in base a una politica interna(es: round robin). Pi bus
possono operare in 2 modi:
1. una parola alla volta, il DMA richiede il trasferimento di una parola e se
la prende, questo meccanismo chiamato cycle stealing, poich il
controller del dispositivo spia e ruba ogni tanto un ciclo occasionale del
bus della CPU, rallentando la CPU.
2. Modalit blocco, il DMA comunica al dispositivo di acquisire il BUS,
trasferisce e poi rilascia(modalit burst), in caso di burst di grande
entit pu tenere ferma la CPU per un tempo considerevole
3. fly-by-mode, Il DMA comunica al controller del dispositivo di trasferire i
dati letti in memoria, possibile far passare i dati scritti nella DMA e
li dopo un altra richiesta da un altra parte.
Per i trasferimenti i controller DMA utilizzano indirizzi fisici(il SO deve
convertire lindirizzo virtuale prima di scrivere il registro address)
Ma perch il controller del disco copia prima i dati nel suo buffer interno?
1. Il bus di sistema potrebbe essere occupato
2. possono verificarsi errori di trasferimento

Prinicpi del software di I/O

Il software che gestisce lI/O deve:

essere indipendente dal dispositivo, ogni device ha un linguaggio macchina


differente, quindi fa comodo avere un linguaggio indipendente dal
dispositivo; Le API devono essere indipendenti dalla periferica(es:
leggere da file(un file da disco, da USB, da dvd ecc senza modificare il
programma che vuole leggere)); si realizza astraendo uno strato software
naming uniforme, schema con il quale nominiamo le periferiche devessere
uniforme, cos possiamo indirizzare i file e i dispositivi nello stesso
modo, il nome associato a un file semplicemente una stringa
gestione degli errori, le periferiche sono soggette a errori(es: settori
danneggiati), la gestione dellerrore dipende dalla specifica, es
cancello, riprovo, quindi lutente sceglie cosa fare indipendentemente
dallerrore.
Implementazione trasferimento sincrono dei dati, l hw funziona in modo
asincrono, cio richiede dati e mentre attende fa altro. Con il sw
possiamo richiede un file e mentre aspettiamo ci blocchiamo il che
richiede:
1) meccanismi di sincronizzazione
2)bufferizzazione per gestiore velocit diverse(buffer underrun)
bufferizzazione, i dati che escono da un dispositivo non possono essere
memorizzati direttamente nella destinazione finale, es un pacchetto che
arriva dalla rete devessere prima analizzato
gestione delle periferiche non condivisibili, tutte quelle risorse non
preeptive

I/O programmato

la stringa da stampare viene assemblata nello spazio utente , il processo utente


fa poi una chiamata di sistema per avere la stampante(se disponibile gli viene
assegnata), il buffer utente viene copiato in un buffer kernel, SO copia il
primo carattere nel registro dati della stampante, e viene stampato,
successivamente la CPU controlla se la stampante pronta a ricevere un nuovo
carattere(polling), dopo che il controller della stampante processa il dato
scrive dei bit in un registro di stato, per indicare al SO che pronta per
stampare(occupa la CPU durante la stampa)

I/O guidato da interrupt

i caratteri vengono stampati man mano che arrivano(senza buffer), quando il SO


scrive nel buffer dei dati della stampante, la stampante invia richiama lo
scheduler(interrupt) per fare in modo che la CPU possa essere riassegnata, una
volta che il carattere stato processato chiama nuovamente un interrupt, in
seguito viene richiamata la procedura di servizio dellinterrupt.

I/O con DMA

come I/O programmato solo che lavora il DMA e non la CPU(pi lento della CPU)

Livelli del Software di I/O

il driver avvia
loperazione sullhardware
e aspetta linterrupt
linterrupt handler
sveglia il driver quando
loperazione stata
completata
Il software deve
specificare il gestore
dellinterruzione. Quando linterrupt handler viene mandato in esecuzione deve:
1. salvare lo stato della CPU
2. viene eseguito un content switch, per caricare il codice di gestione del
device
3. viene effettuato il reset dellinterrupt, si notifica al device che
linterruzione stata gestita e pu riprendere a funzionare
4. esegui codice gestione
5. sveglia driver
6. scheduler()

Il driver(software) il livello in cui avviene la traduzione da operazioni ad


alto livello a quelle del device. Ogni driver del dispositivo gestisce
normalmente un tipo di dispositivo o al massimo una classe di dispositivi
strettamente correlati. I driver possono gestire dispositivi molto diversi, ma
solitamente non una buona idea.
Driver profondamente diversi sono basati sulla stessa tecnologia, es: USB(basata
sui bus seriali)es: dischi, chiavette, fotocamere, mouse ecc

il driver in esecuzione nel kernel


del sistema operativo, cos da poter
accedere allhardware del
dispositivo(accedere ai registri del
controller)
pi efficiente costruire i driver
nello spazio utente, con chiamate di
sistema per leggere e scrivere

esistono due modi per eseguire le funzioni dei driver:


1. compilo le procedure direttamente nel kernel(linking + compile), il
problema che in fase di compilazione devo metterci tutti i driver che mi
servono, e non possiamo sapere quanti driver avremo bisogno, potrei
prevederli tutti, ma consumerei molta memoria
2. caricamento dinamico di moduli, sono oggetti che possono essere linkati e
compilati in esecuzione dal kernel, il kernel esegue anche:
1. inizializzazione della periferica
2. gestire lalimentazione della periferica
3. altre funzioni di init

Funzione driver:

while(true){
ricevi_istruzione()\\bloccante
verifica_parametri()\\controlla che i parametri per loperazione
\\siano corretti
genera_comandi()\\comandi macchina
if(busy)\\accoda_richiesta
else esegui()
pool o block()}
I driver possono appoggiarsi ad altri driver, devono quindi:
1. esportare delle funzionalit
2. importare delle funzionalit

Software indipendente dal dispositivo


astrazioni software che esegue tutte le funzioni comuni a tutti i dispositivi di
I/O

Illustrazione 2: funzioni svolte dal software indipendente dal sistema operativo


Interfacciamento uniforme dei driver dei dispositivi

I driver dispositivi e i dispositivi stessi dovrebbero avere interfacce


uniformi, al fine di evitare di modificare il sistema operativo ogni volta che
si inserisce un nuovo dispositivo.

Interfacciamento uniforme

Illustrazione 3: interfaccia standard e non standard

Un interfaccia diversa implica che i driver hanno a disposizione funzioni


diverse(dal kernel), e le funzioni dei driver a disposizione per il sistema sono
diverse[questa soluzione complica il modello di programmazione].

Un interfaccia standard molto comoda:


1. inserire un nuovo dispositivo nel sistema molto semplice
2. chi conosce i dispositivi sa cosa ci si aspetta da lui
Illustrazione 4: interfacciamento uniforme spiegato dal prof
come funziona? Per ciascuna classe di dispositivi(stampanti, dischi ecc) il
sistema operativo definisce un insieme di funzioni che il sistema operativo deve
supportare. Spesso i driver contengono una tabella contenente puntatori a se
stesso per queste funzioni; quando il driver viene caricato, il sistema
operativo registra lindirizzo di questa tabella di puntatori di funzioni, cos
quando vuole richiamarne una funzione pu fare una chiamata indiretta a questa
tabella.

Illustrazione 5: esempio tabella dispositivi

Naming uniforme

Il SIDSO si occupa di mappare i nomi simbolici dei dispositivi nel driver


adatto. In UNIX un nome di dispositivo es /dev/disk0 specifica un file speciale
speciale(i-node del file speciale, per essere precisi), questo file contiene 2
dati:
1. major device number, usato per localizzare il driver adeguato
2. passato come parametro al driver, per specificare lunit da
leggere/scrivere.
laccesso ai driver realizzato usanto il major number. Tecnicamente i nomi dei
file possono essere scelti in modo arbitrario, ma solitamente sono scelti a
priori, non possiamo modificare lo schema dei nomi.

<major device number, minor device number>

Buffering

la bufferizzazione serve per sincronizzare dispositivi con velocit molto


diverse.
Es: Un processo vuole leggere dati da un modem, possibili strategie:
1. Un processo esegue una read e si sospende finch non ci sono caratteri da
leggere, Ogni carattere in arrivo causa un interrupt, la procedura di
servizio dellinterrupt presenta il carattere al processo e si
blocca(overhead altissimo Illustrazione 6 a)
2. memorizziamo nel processo un buffer di n caratteri e il processo fa una
lettura di n caratteri. La procedura di servizio degli interrupt mette
questi caratteri nel buffer finch non pieno, quando pieno sveglia il
processo. Il problema che la pagina che contiene il buffer potrebbe non
trovarsi in memoria(e quindi come ci scrivo dentro?)
3. manteniamo un buffer allinterno del kernel, quando questo pieno viene
copiato nel buffer dello spazio utente. Problema: che accade quando ai
caratteri che arrivano mentre la pagina con il buffer utente viene letta
da disco?(il buffer kernel pieno) possiamo utilizzare un altro buffer
kernel in modo da alternare i due buffer(buffering doppio)
4. buffer circolare, abbiamo una zona di memoria e due puntatori, uno punta
alla parola libera successiva(dove mettere i dati), laltro punta alla
prima parola dei dati del buffer, quando hanno raggiunto limit tornano
indietro

Illustrazione 6: buffering
il buffer utile anche in output non solo in input. Es un processo vuole fare
loutput di n caratteri, Il sistema ha due possibilit:
1. blocca lutente finch il buffer non pieno, potrebbe richiedere molto
tempo
2. rilascia il processo utente, nel mentre gestisce linput output e lutente
pu fare altro,come fa il processo utente a sapere quando il processo
stato completato? Signal, o interrupt software(programmazione molto
complicata)
Una soluzione usare un buffer kernel(Illustrazione 6 c, ma al contrario, cio
quando il buffer utente pieno copio nel buffer kernel)
Problema: se i dati sono messi nel buffer troppe volte, abbiamo un calo di
prestazioni, Es: Illustrazione 7

un utente fa una
chiamata di sistema per
scrivere nella rete, il
kernel copia il
pacchetto nel buffer
kernel e sblocca il
processo utente; il
driver copia il
pacchetto al controller
per loutput(copia nel
controller perch
altrimenti non possiamo
garantire che il
pacchetto giunga a
velocit uniforme, per
Illustrazione 7 via dei vari cycle
steling ecc ) il resto
si vede dal disegno, tutte queste copie sequenziali rallentano di molto.

Gestione degli errori

Gli errori sono molto frequenti nella gestione delle periferiche abbiamo:
1. rottura delle periferiche, creano errori di lettura scrittura(es: leggere
su un settore del disco danneggiato)
2. errori di programmazione(se ne occupa il driver, e se non sa cosa fare
SIDSO):
un processo richiede qualcosa di impossibile, scrittura su dispositivo
di input
scrittura su un indirizzo del buffer non valido ecc
3.

Quando avvengono il sistema operativo deve gestirli, di ci si occupa il


software indipendente dal sistema operativo. Possibili soluzioni:
1. Tentativo successivo, alcuni errori possono avvenire una sola volta; es:
richiedo la lettura di un USB che non inserito(a senso cliccare
riprova dopo aver inserito la chiavetta), a volte gli errori sono
persistenti es: interfaccia di rete morta, se dopo un tot. Di riprova non
funziona il sistema termina.
Allocazione e rilascio dei dispositivi dedicati

Alcuni dispositivi come il lettore CD possono essere usati solo d aun processo
alla volta. Il sistema operativo deve esaminare le richieste per lutilizzo del
dispositivo e accettarle o rifiutarle a seconda che il dispositivo sia
disponibile o meno, come?
1. Richiedere ai processi di fare la open direttamente sui file speciali, e
la chiusura di tali dispositivi comporta il rilascio del file
2. un tentativo di acquisizione di un dispositivo in uso blocca il chiamante
invece che fallire(i processi bloccati finiscono in una coda)

Dimensione dei blocchi indipendente dal dispositivo

I dispositivi potrebbero avere dimensione dei blocchi molto diverse tra di loro,
ma come fa il sistema a richiedere un blocco se non conosce la dimensione? Se ne
occupa il software indipendente dal dispositivo, fornendo blocchi logici di
dimensione equivalente(magari combinando pi blocchi), e successivamente si
occuper di convertire i blocchi logici in fisici, a seconda del dispositivo

Software di I/O nello spazio utente

Sebbene il software di I/O risieda nel sistema operativo, una piccola parte
composta da librerie connesse al di fuori del kernel, normalmente le chiamate di
sistema sono eseguite da funzioni di libreria es: write, ma ci sono funzioni che
vengono eseguite totalmente in modalit utente es: printf/scanf
stesso discorso spooling

Illustrazione 8: sintesi sistema di I/O


Dischi

esistono molti tipi di disco, i pi comuni sono i dischi rigidi magnetici, con
medesima velocit di lettura e scrittura ; abbiamo anche dischi ottici e infine
dischi a stato solido.

Dischi magnetici

composto da piatti metallici, coperti da materiale magnetizzabile, che


invertendo la polarit possono assumere valori 0 e 1; i dati vengono divisi in
tracce magnetiche, quali sono suddivisi a loro volta in settori, piatti
metallici sono divisi in settori(ognuno contenente una traccia, e con un
indirizzo), i piatti hanno due facce.

Lettura e scrittura avvengono con delle testine ancorate a un braccio che si


muovono in modo trasversale(2 per ogni piatto) il numero di testine(totale)
determina il numero di traccie in un disco.

I dischi pi vecchi hanno poca elettronica, e portano un semplice flusso di bit


in serie. Su questi dischi il controller esegue la maggior parte del lavoro. Sui
dischi IDE e sui SATA lunit del disco stesso a contenere un microcontroller
che svolge una parte considerevole del lavoro e permette al controller reale di
inviare un insieme di comandi ad alto livello, il controller si occupa anche
della cache delle tracce e il rimappaggio dei settori dannegiati.

Una caratteristica molto importante sono le ricerche sovrapposte(overlapped


seek), Mentre il controller e il software sono in attesa che si completi la
ricerca su di ununit, il controller pu iniziare una ricerca su di unaltra
unit(anche sulla stessa unit es: hard-disk con controller integrato almeno
garantita la copia da hard-disk a buffer del controller in simultaneo). In ogni
caso i trasferimenti da controller a memoria sono singoli.

Abbiamo detto che il settore un flusso di bit(solitamente 512 byte), ed


anche lunit fondamentale degli hard-disk, quando voglio scrivere su di
possibile indicare l'indirizzo nell'hard disk e l'operazione che
vogliamo compiere. Il controller selezioner l'azione che ci interessa, sposter
il braccio sulla relativa traccia e aspettiamo che la rotazione del disco faccia
passare la traccia sotto la testina. Il problema ora come indirizziamo i
settori?

Per leggere una certa traccia(di un disco) dobbiamo spostare il braccio avanti
e indietro, quando sposto una testina sposto anche tutte le altre testine nella
pila di dischi, per cui quella che creiamo una geometria a cilindro.
Detto ci, quando vogliamo individuare in modo univoco un settore all'interno di
un hard disk dobbiamo individuare la traccia sulla quale il settore giace,
quindi spostiamo il braccio su quella traccia. In realt non individuiamo una
traccia ma un cilindro di tracce(inteso come tracce verticali)
(Cylinder). All'interno di quel cilindro ci interessa sapere quale piatto e
faccia dei dischi(NB i dischi hanno 2 facce) contiene la traccia, la
individuiamo con la testina (Head). Una volta individuata la
traccia individuiamo il settore. I settori hanno un identificatore numerico che
locale alla traccia nella quale si trovano, quindi va individuato anche il
settore (Sector).

Il tempo di accesso a un settore dato da:

1. seek time(la testina va sulla traccia del settore desiderato);


2. latency time(il settore ruota fin sotto la testina)

Sfruttiamo quindi(per lindirizzamento):

1. Sfruttiamo la geometria fisica del disco, cio la descrizione di quanti


cilindri ha il disco, numero di settori, numero di tracce, numero di
testine ecc
2. C H S, ogni settore ha un indirizzo composto da 3 elementi; il numero di
cilindro, che testina legge 6il numero di settore da leggere

CHS

il CHS viene utilizzato dai microcontroller, lo schema CHS fu sviluppato da IBM


che decise di utilizzare 24 bit(per lindirizzo), ripartizionati come segue:

c=10;h=8;s=6

gli indirizzi sono assegnati dal bios, per evitare che il programmatore dovesse
occuparsi della formattazione del disco.
il settore 0 riservato. Questo ci permette di calcolare la capacit massima:

2^10*2^8*2^6*dimensione dei blocchi(2^9)=2^33/2^30= 8GB, quindi possiamo gestire


hard-disk fino a 8GB, per i dischi di allora questo sembrava un limite molto
molto alto.

Successivamente ATA rilasci uno standard CHS, che prevedeva:


c=16 h=4 s=8 con capacit di totale di 128GB

Allepoca per molti dischi utilizzavano ancora i vecchi CHS quindi per poter
utilizzare linterfaccia ATA sulle macchine CHS si prendeva il minimo tra i due
quindi: c=10 h=4 s=6 ottenendo una capacit di indirizzamento di soli 512MB

Ci che fece ATA per risolvere questo problema fu modificare lo schema di


indirizzamento(mantenendo il CHS)
LBA(Logical Block Addressing)
sono indirizzi lineari, nasce a 22 bit successivamente passa a 24 e 48, i quali
possono gestire dischi della capacit di 2^50 byte; a questo punto sorge una
domanda come posso usare LBA, usando macchine con bios CHS?
Utilizziamo la geometria del disco: il primo indirizzo LBA viene assegnato al
primo settore del primo patto e a spirale assegnamo gli indirizzi
successivi(quando la traccia termina passo alla traccia di sotto e cos via,
iniziando nuovamente il conteggio) procedendo per cilindri.
Come passo da chs allindirizzo LBA?

A(indirizzo LBA)=(c*Nh(numero di testine)+h*Ns(numero settori dalla geometria


del disco) +s-1)

e se il bios usasse LBA, ma il disco ha come schema interno CHS?

c= LBA /(Nh*Ns)
h=(LBA/Ns)%Nh
s=(LBA%Ns)+1

Illustrazione 9: man mano che ci allontaniamo dal centro i settori diventano pi grossi, e la
velocit angolare aumenta, il ch ci consente di avere pi settori per traccia, il tutto si realizza
utilizzando una geometria virtuale del disco che viene presentata al sistema operativo, il controller
rimapper poi la richiesta di (c,h,s) nella testina e settori reali.

Testo 1: possibili geometrie virtuali

Testo 2: si introducono le geometrie virtuali perch il numero di settori per disco non sempre lo
stesso(vedasi testo di sopra)
I dischi moderni sono molto veloci. Il disco SAS (Serial Attached SCSI) o SATA
(Serial Advanced Technology Attachment)
si differisce non dall'interno, ma dall'interfaccia esterna. Se prendo un SSD
con un'interfaccia lenta pi di una certa velocit non potr avere.
L'interfaccia attualmente pi veloce la SAS con stato solido interno, che
opera a 12 Gbit/s = 1,5GB/s. Ma anche le altre memorie hanno continuato a
velocizzarsi. Le RAM pi veloci al momento sono le DDR3, a 3000 hz, che
trasferiscono dati a 24 GB/s. I dischi di punta sono 15 volte pi lenti della
memoria normale. Questo un problema perch ogni volta che cerchiamo di leggere
dati da un dispositivo di memoria di massa la CPU deve fermarsi per un mucchio
di tempo, ci inventiamo dei congegni (DMA,ecc.) per ridurre il disagio. Nei casi
migliori la CPU dovr aspettare un tempo di 15 volte pi lenta rispetto alla
RAM.
Raid(array ridonandante di dischi economici)

Come rendiamo i dischi pi veloci? Si basa sulla stessa idea con cui si sono
rese le CPU pi veloci, cio il parallelismo, rispetto ai vecchi SLED
Raid Livelli(guardare quaderno)

lidea alla base dei RAID installare un contenitore pieno di dischi accanto al
computer a questo punto sostituiamo la scheda controller dei dischi con un
controller RAID

Ho un controller al quale sono collegati dei dischi basati sulla


tecnica dello stripping. Stripping: i dati li organizzo in blocchi, ciascuno dei
quali consiste in un gruppo di settori consecutivi e questi blocchi si chiamano
strip. Consiste nel vedere il singolo disco virtuale simulato dal RAID come se
fosse diviso in strip di k settori ciascuna. Al controller arrivano le richieste
per i settori, il controller non fa vedere al sistema i vari dischi, ma un unico
disco. Quando il driver chiede un settore lo chiede dall'intero pool di dischi,
non dallo specifico disco. Per individuare un settore divido l'indirizzo per il
numero di strip (es. 4) e calcolo quel risultato in modulo x dove x il numero
di dischi collegati al RAID.
I dati allinterno dei dischi sono replicati in tutti i dischi.

RAID 0

Basato unicamente sulla tecnica della striping, non presenta ridondanze, le


varie stripe sono distribuite sui dischi in modalit round-robin; Questo modello
non presenta ridondanza, se la lettura interessa un intera stripe abbiamo
prestazioni massime, poich possiamo leggere in parallelo;

Abbiamo per un problema legato all'affidabilit. Le specifiche dei costruttori


di harddisk esprimono l'affidabilit con un'unit di misura MTTF (Mean Time To
Failure),tempo medio che trascorre tra due guasti, il tempo da quando uso un
disco a quando si romper.

Supponiamo di avere un sistema raid0 a 4 dischi ciascuno con un MTTF pari a


20.000 ore. Qual' la probabilit che quel disco sia funzionante quando cerco di
usarlo? Il reciproco dell'MTTF, 1/20.000 = 0,00005, una probabilit abbastanza
bassa.

Consideriamo cosa vuol dire mettere insieme i 4 dischi facendoli vedere come un
disco unico. Ci vuol dire che perch il sistema funzioni correttamente ciascuno
dei 4 dischi deve essere funzionante, quindi la probabilit che il sistema si
guasti data dalla probabilit che si guasti il primo oppure il secondo, oppure
il terzo oppure il quarto. I dischi si guastano indipendentemente l'uno
dall'altro, quindi la probabilit data da P1 + P2 + P3 + P4 = 0,0002, con il
reciproco pari ad un MTTF pari a 5000. Si passa da un disco che si rompeva
dopo 20.000 ore ad uno che si rompe dopo 5.000 ore, molto meno affidabile.

Inoltre i sistemi operativi che chiedono un settore alla volta non sfruttano il
parallelismo

RAID 1
Per ovviare ai problemi visti in precedenza adottiamo la tecnica del mirroring,
cio copie speculari dei dati, dato un gruppo di n dischi li divido in n/2
dischi, per ciascun disco dichiaro un secondario, cos se un disco si rompe il
disco continua a funzionare, la tolleranza ai guasti del raid1 pi alta del
raid0, si possono rompere fino a n/2 dischi, e il sistema continua a funzionare.

In termini di prestazioni in lettura equivalente, poich possiamo utilizzare i


dischi secondari per la lettura in parallelo, mentre in scrittura raid1 pi
oneroso, poch dobbiamo scriver i duplicati.

NB anche in questo modello abbiamo strip di k settori ciascuna, ognuna


memorizzata su un disco

La capacit utile circa la met rispetto a raid 0

Esistono soluzioni in cui si usa meno ridondanza, al fine di ottenere una


maggiore capacit utile, e si mantiene la tolleranza ai guasti.
RAID 2

Si fa striping a livello dei singoli bit, cio si decide l'unita elementare, nel
nostro esempio mezzo byte, e si distribuiscono i bit sui dischi

i tre bit rimanenti sono utilizzati per il codice di hamming che ne garantisce
l'affidabilit.

Per ottenere prestazioni migliori potrei scegliere come dimensione della strip
32 bit, come le parole di memoria questo portebbe ad avere un totale di 38
dischi.

Problema, se devo fare una lettura su 32 dischi diversi, il controller deve


mantenere tutte le testine allineate sui diversi dischi, nasce un problema
dovuto alla dilatazione termica, dovuta alla rotazione dei dischi, che farebbe
perdere la calibratura delle testine molto facilmente. Inoltre posso correggere
errori di un solo bit

RAID 3

Manteniamo i bit come dimensione delle singole strip, ma utilizziamo un singolo


bit di parit
Il bit di parit dev'essere aggiunto in modo da rendere la somma degli 1 pari

Illustrazione 10: Quando scrivo i dati, il controller conta il numero di 1 e aggiunge di


conseguenza il bit di parit

Letture e scritture avvengono come in raid2, cio le testine devono essere


perfettamente sincronizzate, pich le singole parole dati sono distribuite su
pi unit.

Il problema che il bit di parit non consente di correggere gli errori, posso
solo rivelarli, ma se si rompe un disco possiamo ricostruire l'informazione
guardando il bit di parit, se si rompono due dischi non posso pi recuperare
nulla.

Un altro problema dovuto al fatto che sulla singola richiesta vado molto
velocemente, per il throughput basso, poich per una singola richiesta devo
utilizzare tutti i dischi, quindi le richieste si accodano. Capacit totale=
C(N-1), dove C la capacit di un disco e N-1 il numero di dischi. Il problema
vero di questa soluzione che l'unit fondamentale dei dischi il settore 512
byte, per ogni settore devo portare in memoria 512 * 8 bit; il che una
procedura molto molto lenta.

RAID 4

Abbiamo strip di blocchi(diversi settori). Data una batteria di N dischi N-1


saranno utilizzati per i dati e 1 per la parit

L'idea di mettere in XOR l'intera stripe per calcolare la strip di parit.

Dp(x)=D1(x) XOR D2(x) XOR XOR Dn(x)

Se si rompe un disco posso ricostruire l'informazione in questo modo:

Dr(x)= D1(x) XOR XOR Di(x) XOR Di+2(x) XOR Dn(x)

Illustrazione 11: si sfrutta la propriet che un valore in XOR con se stesso si annulla
Se si rompono due dischi non gi pi possibile corregere

Prestazioni

Lettura:

1. se la lettura conivolge una stripe intera, allora otterr massimo


parallelismo, tutti i dischi sono coinvolti
2. per letture piccole, es qualche strip, le letture saranno altrettanto
buone, posso parallelizzare anche queste, ottenendo un buon throughput

Scrittura:
Le operazioni di scrittura interessano anche il disco di parit, poich devo
aggiornare le informazioni in esso contenute
1. Intera stripe, nessun problema, il controller ha in memoria tutte le
strip, e pu facilmente calcolare le informazioni di parit
2. Strip, in controller avr in memoria soltanto le informazioni riguardanti
la strip, dovrei impegnare gli altri dischi nella lettura delle strip
mancanti, il che portebbe a uno svantaggio
Possiamo sfruttare una propriet dello XOR per non dover ripescare ogni
volta tutte le strip

3. Pnew=Pold XOR Di(new) XOR Di(old), ricava da Pold(x) XOR Pnew(x) XOR
Pold(x) = Dinew(x) XOR diold(x) XOR Pold(x)

Al posto di leggere l'intera stripe mi basta leggere la vecchia informazione di


parit, e il valore della vecchia strip. il problema delle small write.
Il disco di parit un collo di bottiglia, se devo eseguire 4 write di 4 strip
su stripe diverse, esse non possono essere eseguite in parallelo, poich devo
per ciascuna aggiornare l'informazioni di parit

RAID 5

Come il RAID 4, solo che l'informazione di parit distribuita su tutti i


dischi, in che modo?

Si utilizza una tecnica basata sul modulo l'informazione di parit rispetto alla
stripe i dev'essere memorizzata in (N+i)%N; Una distribuzione del genere detta
left-symmetric, esistono altre distribuzioni della parit.

In questo modo posso parallelizzare le small write su N dischi differenti, resta


comunque il fatto che devo recuperare le giuste informazioni per aggiornare la
parit

Recupero dati

In caso si rompa un disco posso utilizzare il disco di ridondanza(Proprio come


RAID 4), utilizzando

RAID 6 e p+q

In p+q aggiungo ridondanza(2 dischi di parit) e attraverso l'utilizzo di codici


read solomon ricostruisco l'informazione su 2 dischi. Data una stripe , read
solomon, restituisce 2 informazioni p e q entrambe capaci di ricostruire
l'informazione

Il raid 6 costa di pi in caso di guasta e devo fare 6 piccole letture per ogni
small write.
Formattazione dei dischi

Dopo la produzione dei dischi, non vi alcuna informazione su di essi, ma chi


ci mette le traccie allora? Viene eseguita una formattazione a basso livello,
concentricamente vengono scritte le traccie ognuna delle quali conterr un certo
numero di settori

Illustration 13
Illustration 12: Formato dei settori

Problema
Supponiamo di voler leggere 18 settori a partire dal settore 0 della traccia pi
interna, la lettura dei primi 16 settori avviene tramite la rotazione del disco
mentre per posizionarci sulla nuova traccia, dove si trova il settore 17,
abbiamo bisogno di una seek, mentre effettuiamo il seek il settore 0 passato
sotto la traccia e cos dobbiamo aspettare un intera rotazione del disco per
posizionarci al settore 0

Screw
Dopo la formattazione i settori, solitamente, sono allineati radialmente, ci,
che facciamo invece spostare di un certo offset(chiamato cylinder skew) il
settore 0 di ciascuna traccia rispetto alla traccia precedente; In questo modo
possiamo leggere pi tracce senza perdere dati,lidea chiara, mentre faccio la
seek il disco ruota e quando la testina si sar posizionata sar sul settore 0.

Lo screw dipende da molti fattori:

Screw = Tseek(dipendente dalla meccanica del disco)/Tsettore

Tsettore=TgiroCompleto/numeroSettori Ttraccia=1/velocit di rotazione

ES:

velocitRotazione = 10.000 RPM Tseek= 800 s SettoriPerTraccia=300

Ttraccia=1/10.000RPM =1/(10.000/60)=0,006s =6msec

Tsettore = Ttraccia/SettoriTraccia=6ms/300=0,02ms

skrew = Tseek/Tsettore = 800 s/20 s= 40

Byte per traccia 300 * 512 = 153.600 bytes. Tuttavia so che una traccia

viene letta in 6 ms quindi la velocit di trasferimento che posso ottenere


153.600 * 6/1000 byte/s = 24,4 MB/s. Per pi alta la velocit di rotazione e
maggiore l'usura meccanica dell'hard disk e minore la durata della vita
dell'hard disk.

Ultimamente si preferiscono dischi a bassa velocit.


Un settore corrisponde a una struttura dati memorizzata nella traccia;
Lo spazio per ECC(maggiore lo spazio di questo campo maggiore il numero di
errori che possiamo correggere) preambolo e settori di scorta riduce lo spazio
di un disco (20%)

Come fa il controller a trasferire dati sulla macchina?

Il controller deve scrivere questi dati in memoria principale, tuttavia vi sono


delle operazioni che deve svolgere prima di fare questo, come calcolare lECC e
confrontarlo con ECC del settore ed eventualmente correggerlo, durante questi
controlli il settore risiede temporaneamente nel buffer interno del controller,
quanto devono essere grandi?

Almeno quanto un settore, si tratta comunque di memoria molto costosa

loperazione di copia nel buffer interno, controllo ECC e copia in memoria porta
via molto tempo, supponendo di voler leggere + settori con un buffer interno di
1 settore, mentre faccio i controlli sul primo settore gli altri scorrono sotto
la testina e non faccio in tempo a leggerli per il prossimo
Per risolvere il problema utilizziamo la numerazione interlacciata(interliving)

Tipicamente si numerano i settori in modo da non avere due settori consecutivi


vicini, in questo modo leggo 0(faccio tutte le operazioni descritte prima) e poi
posso leggere tranquillamente 2 senza il delay di rotazione; se la lettura
particolarmente lenta ho bisogno di un interliving doppio.

Grandezza sfasamento:

1. Almeno il tempo che ci metto a liberare il buffer(Tecc)


2. tempo di settore(testina che routa sotto un settore Tsettore)

Interliving = Tecc/Tsettore

ES calcolo sfasamento

Tecc = 12 ns
Tsettori= Ttraccia/NsettoriTraccia
Ttraccia = 1
settore= 1024byte
velocit di rotazione = 15k BPM
settori per traccia = 1000

Ttraccia = 1/(15k/60)=4ms

Tsettore=4ms/1000 = 4ns
I=12ns/4ns=3

VtrasferimentoDati=(BpT/(Ttraccia))/1000(MB)

Per evitare linterliving solitamente si da la possibilit al controller di


bufferizzare un intera traccia.

Il numero di settori letti dipende da velocit di rotazione e settori per


traccia, questo se tutti i settori sono sulla stessa traccia, altrimenti devo
fare una seek, poi devo aspettare che il settore transiti sulla testina e poi
copio nel buffer e infine finir nel driver.

Taccesso = Tseek + Trotazione + Ttrasferimento

Gli ultimi due dipendono dalla geometria del disco mentre il tempo di seek
dipende dal numero di settori su tracce diversi. Esistono meccanismi per ridurre
il tempo di seek(algoritmi di scheduling del braccio del disco), lidea che il
driver calcoli il cilindro su cui sono memorizzati i settori per cui arrivano
richieste e passi al controller gli indirizzi dei settori da leggere(riordinando
le richieste)
Algoritmi di scheduling del braccio

Se il driver del disco accetta una sola richiesta alla volta, e le esegue nello
stesso ordine c ben poco da ottimizzare, ma normalmente i driver tengono
traccia in una tabella indicizzata per numero di cilindro, di tutte le richieste
per ciascun cilindro; attraverso lutilizzo di questa tabella possiamo
migliorare FCFS, riordinando le richieste in modo da eseguire pochi seek.

Supponiamo di avere un hard-disk contenente 40 cilindri, mentre leggiamo 11,


arrivano diverse richieste: 1,36,16,34,9 e 12, quando finisce 11 chi eseguiamo?

Illustrazione 14: situazione descritta prima in cui si usa SSF


In caso usassimo FCFS dovremmo attraversare un numero di cilindri pari a:

11-1(10)+1-36(35)+36-16(20)+16-34(18)+34-9(25)+9-12(3)=111

Per ridurre i tempi di ricerca possiamo eseguire le richieste ai cilindri pi


vicini, quindi seguendo lesempio di prima riordiniamo le richieste nel seguente
modo:
12,9,16,1,34,36 Con questo algoritmo attraversiamo soltanto 61 cilindri SSF, il
problema che se il carico di lavoro elevato il braccio del disco rester pi
tempo nel mezzo rispetto agli estremi(starvation), supponiamo di essere in 16 e
che arrivi una richiesta 13, questa verr eseguita, ma se arrivano moltissime
richieste molto probabile che il braccio rimanga nel mezzo a servirle, finch
non ve ne saranno pi.

Algoritmo dellascensore(detto anche SCAN), vi un bit UP/DOWN, al termine di


una richiesta il driver del disco controlla il bit, se UP(il driver passa al
controller la prossima richiesta verso lalto) il braccio viene spostato verso
la prossima richiesta verso lalto, altrimenti se il bit DOWN, il braccio si
sposta verso il basso
Illustrazione 15: Trattasi della versione che solitamente si implementa(detta LOOK)
Detto in parole povere mi muovo verso lalto, finch non incontro la fine,
quindi nel nostro esempio il cilindro 40 poi torno indietro e servo le richieste
che incontro; parallelamente lalgoritmo che di solito viene implementato pi
simile a quello dellillustrazione 13, e viene chiamato LOOK, al posto di
spostarsi fino alla fine arriva fino allultima richiesta.

Ma anche questo metodo favorisce le richieste nel mezzo, poich ci passo


esattamente 2 volte, in una sola passata rispetto ai lati, per ottenere pi
uniformit utilizziamo una piccola modifica, al posto di tornare indietro mi
sposto in una sola direzione.

CSCAN, le tracce vengono considerate come liste circolari in cui lultima


adiacente alla prima.

Serve tutte le richieste fino alla fine, poi torna indietro senza servire
richieste(arriva al cilindro 0) e poi si sposta nuovamente in avanti

CLOOK la versione ottimizzata, ci spostiamo fino allultima richiesta e poi


torniamo indietro fino alla prima richiesta senza servire

Gestione degli errori(pag. 339)

Interfacce utente:tastiera, mouse ecc (pag. 350)

Gestione del risparmio energetico(pag. 372)

You might also like