Estratto del documento

Interazione con le periferiche e istruzioni processore

Per interagire con le periferiche, i processori utilizzano delle istruzioni apposite privilegiate, IN OUT che nell'x64 prendono come operando l'indirizzo (detto anche PORT) di un registro della periferica. Permettono quindi la lettura e la scrittura sui registri. Ogni periferica possiede fisicamente un adattatore che realizza l'interfaccia con la macchina e consiste in alcuni registri per la comunicazione con il sistema.

Registri periferica

  • Registro dati: contiene i dati da leggere o scrivere
  • Registro comandi: contiene le istruzioni da eseguire sulla periferica
  • Registro di stato: contiene informazioni sullo stato attuale della periferica, come il bit READY che indica se la periferica è pronta o occupata

Gestione dell'I/O

La gestione dell'I/O può avvenire in tre modi:

  • A controllo di programma
  • Meccanismo di interrupt
  • Accesso diretto alla memoria (DMA)

Queste tecniche di gestione devono consentire delle interazioni fondamentali tra periferica e computer, in particolare la sincronizzazione e il trasferimento dati.

A controllo di programma

Il metodo a controllo di programma è una schifezza che non si usa. Semplicemente fa un ciclo while in cui il programma controlla se la periferica è pronta e quando è pronta fa il trasferimento. Questo significa che durante l'attesa il processore non fa niente.

Meccanismo di interrupt

È già più sensato il meccanismo di interrupt che abbiamo già studiato a fondo nelle precedenti lezioni. Il processore fa altre cose e quando la periferica è pronta (cioè il bit Ready passa da 0 a 1) invia un interrupt al processore. Sono necessari degli eventi che generino l'interrupt e delle routine che eseguano le istruzioni associate.

Accesso diretto alla memoria (DMA)

Il più figo è l'ultimo: tramite un adattatore DMA (DMAC) il trasferimento dati tra periferiche e memoria avviene autonomamente senza l'intervento del processore. Esso deve solo scrivere nell'adattatore l'indirizzo da cui iniziare il trasferimento nella periferica, l'indirizzo da cui iniziare il trasferimento nella memoria, il numero di byte da trasferire e la direzione. A questo punto setta il bit Start e va a fare altro. Ci penserà poi un singolo interrupt finale (e non ad ogni byte) ad avvisare il processore del completamento dell'operazione.

Per implementare questo metodo, il sistema operativo deve dedicare delle zone di memoria per il trasferimento dati tra periferiche in modalità DMA, ovvero dei buffer. Tra l'altro, Linux differenzia i device driver in due categorie:

  • Block devices: trasferiscono dati a blocchi e fanno uso di DMA (per esempio i dischi e tutte le unità che hanno accesso casuale)
  • Character devices: periferiche a caratteri come tastiere e stampanti (hanno accesso sequenziale)

Periferiche per la memoria di massa

Le periferiche per la memoria di massa possono essere degli hard disk drives (HDD) oppure dei solid state drives (SSD). Sono trattate con il concetto di LBA (Logical Block Address), cioè sono viste come degli array sequenziali di blocchi da 512 byte ciascuno (o un suo multiplo). Chiameremo volume un generico dispositivo per la memoria non-volatile con indirizzamento LBA. I blocchi sono l'unità di informazione fondamentale trasferita tra memoria di massa e volume.

Un disco rigido può essere diviso in tracce (anelli concentrici), settori (fette di torta), tracce del settore (l'intersezione tra i due), piatti (se c'è più di un disco, come è di solito), cluster (tracce del settore contigue), cilindri (tracce su più piatti). Gli hard disk sono lenti perché c'è di mezzo il movimento meccanico della testina che deve andare sulla traccia giusta nonché il ritardo di rotazione.

Comunicazione tramite bus

La comunicazione tra il processore e le altre unità funzionali del calcolatore avviene tramite i bus. Questi possono essere bus interni o bus esterni rispetto alla CPU. Il bus esterno è unico ed è chiamato bus di sistema, che poi si divide in bus specializzati:

  • Bus alimentazione
  • Bus dati: permette il passaggio di informazioni, è utilizzabile da tutti sia in lettura che in scrittura
  • Bus indirizzi: seleziona gli indirizzi, è scrivibile solo dalla CPU e in sola lettura per tutti gli altri
  • Bus controlli o Bus controller: deve coordinare i bus

Il bus di sistema deve permettere le transazioni di trasferimento e le transazioni degli interrupt. I bus normalmente permettono di trasferire una quantità di dati pari alla lunghezza dei registri della CPU (quindi 32 o 64 bit). In quest'ultimo caso servono due segnali: INT_REQ viene emesso dalla periferica che richiede l'interrupt verso la CPU e INT_ACK viene emesso dalla CPU per segnalare alla periferica che l'interrupt è stato accettato.

Per non creare delle linee di bus per ogni singola periferica (roba da nabbi) si usa un metodo più ingegnoso: esistono due linee per questi segnali che sono condivise da tutte le periferiche. L'INT_REQ è in WIRED OR mentre l'INT_ACK è in DAISY CHAIN. Se nessuna periferica invia un interrupt, la linea INT_REQ rimane a riposo, mentre se una lo invia, essa viene attivata (è appunto l'OR di tutti gli INT_REQ). Per questioni elettroniche il segnale INT_REQ è a 1 quando nessuno invia richiesta, quindi nel processore c'è un negatore per far quadrare tutto. Il segnale di INT_ACK invece viene propagato a tutte le periferiche una dopo l'altra finché trova quella che ha inviato l'interrupt. A quel punto il segnale di INT_REQ viene disattivato dalla periferica e si procede con la routine richiesta.

Transazione di trasferimento

Per la transazione di trasferimento, si seleziona un'unità, detta master, che controlla il bus durante l'operazione. Questo sceglierà la periferica con cui effettuare il trasferimento (detta slave) e l'operazione da compiere (lettura/scrittura sul segnale R/W). A questo punto esegue il trasferimento vero e proprio. I componenti che possono diventare master sono le CPU, i coprocessori e i DMAC. Per la scelta del master c'è un'unità specializzata che funge da arbitro del bus (può essere la CPU stessa). L'arbitraggio procede in parallelo: cioè mentre il master fa le sue cose, l'arbitro decide chi sarà il prossimo master. I segnali utilizzati sono BUS_REQ (indica la richiesta di essere mastership), BUS_GRANT (indica l'accettazione della richiesta di mastership) e BUS_BUSY (asserito dal master corrente, il prossimo master può leggerlo per sapere quando è il suo turno).

File system

Il file system è quel componente del sistema operativo che si occupa della gestione dei file, perciò è molto importante. Linux poi è fatto bene e permette di gestire File System diversi (da Ext4 a NTFS a ISO 9660) perché fa uso dell'interfaccia VFS (Virtual Filesystem Switch) che è simile alle classi dello scheduler, per cui ogni funzione di VFS è un puntatore all'effettiva funzione del file system usato al momento.

Componenti di un file

  • Una sequenza di byte
  • Un nome simbolico e univoco nella directory
  • Attributi vari (tipo, percorso, dimensione, protezione, timestamp, proprietario)

Tipi di file

  • File normali: Contenitori di dati o programmi
  • Directory: Riferimenti ad altri file
  • File speciali: Astrazione di periferiche fisiche

Sappiamo che il C usa funzioni di libreria per maneggiare i file come fopen, fclose, fread, fwrite, fputs, fgets... e i file sono puntatori di tipo. Queste funzioni però chiamano delle routine di sistema di più basso livello che invece non maneggiano puntatori ma il descrittore del file. Una panoramica di queste funzioni:

  • int creat(char *file_name, int permessi)
  • int open(char *file_name, int rw, int permessi)
  • void close(int fd)
  • int read(int fd, char buffer[], int numero)
  • int write(int fd, char buffer[], int numero)
  • long lseek(int fd, long offset, int riferimento) // 0 = inizio, 1 = pos. corrente, 2 = fine
  • void link(char *old_file_name, char *new_file_name)
  • void unlink(char *file_name)
  • int dup(int fd) // duplica file ma condivide il puntatore seek

Struttura del file system

Un file system è suddiviso in:

  • Partizioni
  • Directory (tra le quali quella principale è la root directory)
  • File ordinari

Il pathname può essere assoluto (cioè a partire dalla directory di root) oppure relativo (a partire dalla directory corrente). I file speciali, abbiamo visto, sono i file con cui si rappresentano le periferiche. Sono memorizzati nella cartella /dev. Ogni programma ha sempre tre file aperti che sono stdin (0), stdout (1) e stderr (2). Nella cartella /bin si trovano gli applicativi che di solito sono condivisi tra gli utenti.

Comandi e protezione dei file

Per creare una nuova directory si usa mkdir e per creare un nuovo file speciale si usa mknod. Non si usa creat.

Per la protezione dei file, in Linux gli utenti sono suddivisi in tre categorie:

  • Owner Proprietario del file
  • Group Utenti appartenenti al gruppo del proprietario
  • All Tutti

Le operazioni su file si suddividono in tre classi:

  • Read Lettura, copia
  • Write Scrittura, modifica, eliminazione
  • Execute Esecuzione

Ad ogni file così si associano:

  • Owner
  • Group
  • Control Access List

Quest'ultimo è una sequenza formata da tre gruppi di bit che indicano rispettivamente i diritti di accesso di owner, group e all con un numero da 0 a 7 che rappresenta i flag rwx.

Gestione del disco rigido e filesystem

Allora avevamo detto che nel disco rigido ci stanno tracce e settori, mentre dal punto di vista logico ci sono volumi e blocchi da 512 byte in un array. Per prima cosa la traduzione da un sistema all'altro è compito del driver. Ogni volume è come se fosse una partizione, cioè ognuno ha il suo file system ed è visto come un dispositivo distinto.

Dicevamo anche che, quando possibile, alcuni dati del disco vengono tenuti in memoria per un futuro uso e questo è il compito del gestore del buffer. Quindi quando il file system chiede la lettura di un file, questo interagisce con il gestore del buffer che, a sua volta, potrebbe interagire con il disk driver. Nel caso di periferiche a carattere, il file system interagisce direttamente con il driver senza passare per il buffer.

Struttura di un volume

Un volume è diviso in quattro categorie:

  • Blocco di bootstrap (0)
  • Superblock (1)
  • I-list
  • Dati

Il blocco di bootstrap è nel primo settore e contiene il codice di inizializzazione del SO. Il superblock contiene informazioni generali del file system. La i-list contiene gli i-node, cioè i riferimenti ai blocchi dati dei file sul disco. I blocchi dati contengono i dati effettivi.

Nota che si capisce subito una cosa: tutto ha un limite, la i-list ha a disposizione un numero prefissato di blocchi (scelto al momento della creazione del file system con mkfs), quindi possono esserci un numero massimo di i-node, cioè anche di file! Inoltre noi ci basiamo su un file system un po' vecchiotto... Quelli recenti funzionano allo stesso modo più o meno, ma permettono di memorizzare molti più file, mentre questo qua ha delle dimensioni ridicole per un PC attuale, infatti un i-node ha dimensione di appena 64 byte.

È accessibile attraverso l'indice della lista (I-NUMBER). Le directory possono essere viste come tabelle contenenti il nome di ogni file associato al suo i-node. Ma vediamo cosa c'è in questi miseri 64 byte:

  • Tipo: d per directory, b per block device, c per character device, 0 per libero
  • Owner del file e suo Group
  • Control Access List (i 9 bit di rwx)
  • Numero di link al nodo (quando questo numero va a zero il file viene "cancellato" nel senso che si cancella il suo i-node)
  • Dimensione del file in blocchi
  • Puntatori a blocchi dell'area dati: 13 indirizzi di tipo diretto o indiretto (non sono usati per i file speciali, perché non servono)
  • Timestamp

Dei 13 puntatori solo 10 sono a indirizzamento diretto, mentre gli altri 3 puntano a delle tabelle di supporto sempre più grandi (da 128 indirizzi) per permettere l'esistenza di file di grandi dimensioni (in realtà in questo file system la dimensione massima è appena 1 GB, i file system moderni consentono file da 16 TB, cioè che non possono manco essere contenuti nei più grandi hard disk in circolazione).

Contenuto del superblock

  • Dimensione del volume
  • Numero di blocchi liberi
  • Parte iniziale della lista dei blocchi liberi (Free List)
  • Numero di elementi nella i-list (cioè numero di i-node o di file)
  • Numero di i-node liberi (Free I-nodes)
  • Lista degli i-node liberi (Free I-node List)
  • Informazioni ausiliarie varie

La lista dei blocchi liberi è molto grande (enorme alla creazione del file system perché il disco è vuoto). Per questo il superblocco contiene solo la parte iniziale della lista, mentre gli altri elementi sono nei blocchi dati concatenati tra loro (cioè il primo elemento della lista punta ad un'altra lista).

Gestione del file system

Per la gestione del file system il sistema operativo dispone di tre tabelle in memoria centrale che sono:

  • Tabella dei descrittori dei file aperti: ne esiste una per ogni processo e contiene i riferimenti ai file aperti in un determinato processo
  • Tabella globale dei file aperti: contiene i riferimenti a tutti i file attualmente aperti sul sistema
  • Tabella degli in-core i-node: è una copia degli i-node più usati recentemente

Nella tabella dei descrittori dei file aperti, si usa il descrittore come indice e ogni entry contiene l'indice della riga della tabella globale dei file aperti. Nella tabella globale dei file aperti, l'indice è il numero proveniente dalla tabella dei descrittori. Ogni entry contiene:

  • L'offset all'interno del file
  • La modalità di utilizzo (lettura, scrittura)
  • Numero di riferimenti a questo file dalle tabelle dei descrittori
  • Indice del corrispondente i-node nella tabella degli i-node

La tabella degli i-node è indicizzata tramite la tabella globale dei file e contiene delle copie degli i-node per maggiore efficienza. Oltre al contenuto dell'i-node, possiede anche il numero di riferimenti all'i-node dalla tabella globale e informazioni sul suo stato (es. l'i-node o il file sono stati modificati e devono essere riscritti su disco).

Casi particolari

  • Un processo apre lo stesso file due volte: Sia nella tabella privata che in quella globale si generano due entry distinte. Gli offset e le modalità di accesso possono quindi essere diversi.
  • Un processo duplica un file: Si aggiunge una istanza nella tabella dei descrittori, ma i due file duplicati punteranno allo stesso elemento della tabella globale. Duplicando un file quindi rimane un unico offset globale e un unico metodo di accesso.
  • Un processo genera un figlio: I file del figlio sono duplicati, quindi ci si riconduce al caso precedente.
  • Due processi aprono lo stesso file: Vengono generate due entry distinte anche nella tabella globale. I processi sono infatti indipendenti e ognuno può accedervi col suo offset e la sua modalità. In ogni caso la tabella globale farà poi riferimento allo stesso i-node.

Device drivers

I device drivers, a differenza del file system, si intrecciano maggiormente con il kernel del sistema operativo ed hanno un ruolo fondamentale dato che hanno il compito di far interagire le periferiche con il resto della macchina. I driver infatti occupano gran parte del codice di un sistema operativo e sono in continua evoluzione. Chi scrive driver deve conoscere a menadito l'hardware della periferica e il funzionamento del sistema operativo per cui esso viene scritto.

Avevamo parlato dei device a blocchi e a carattere. La vera differenza è che i block device hanno un indirizzamento casuale e fanno uso del gestore del buffer, mentre i character device hanno indirizzamento sequenziale e si interfacciano direttamente con il file system. Il fatto che si chiamino "character" è perché in passato leggevano un carattere alla volta, ma anch'esse oggi leggono blocchi di dati alla volta.

Le periferiche sono viste come dei file speciali, e lo sappiamo bene, ma sono anche identificate attraverso due numeri detti major e minor. Le periferiche dello stesso tipo (cioè gestite da un driver comune) hanno lo stesso major. Il minor permette di distinguere le periferiche dello stesso tipo. Sappiamo anche che i file speciali non si creano con la funzione creat, ma con mknod, che prende come parametri il pathname, il tipo di periferica (c = character, b = block) e i valori di major e minor. Questi ultimi vengono inseriti nell'i-node del file speciale, che non contiene indirizzi.

Funzioni principali di un driver

  • Inizializzare del dispositivo al bootstrap
  • Porre la periferica in servizio o fuori servizio
  • Ricevere dati dalla periferica
  • Inviare dati dalla periferica
  • Gestire gli errori
  • Gestire gli interrupt

Ogni gestore dispone di una tabella delle operazioni che consiste in una struttura di puntatori alle funzioni che gestiscono le varie routine (open, read, write ecc...). All'avvio del sistema operativo, vengono avviate le operazioni di inizializzazione di tutti i driver, i quali restituiranno al kernel un puntatore alla propria tabella delle operazioni. Il sistema operativo dispone di una tabella dei gestori a blocchi e di una tabella dei gestori a carattere contenenti i puntatori alle tabelle delle operazioni. Nel caso dei gestori a carattere, la tabella è indicizzata con il major del driver, mentre il minor è usato come parametro.

Anteprima
Vedrai una selezione di 12 pagine su 52
Appunti completi corso Sistemi Operativi Pag. 1 Appunti completi corso Sistemi Operativi Pag. 2
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 6
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 11
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 16
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 21
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 26
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 31
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 36
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 41
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 46
Anteprima di 12 pagg. su 52.
Scarica il documento per vederlo tutto.
Appunti completi corso Sistemi Operativi Pag. 51
1 su 52
D/illustrazione/soddisfatti o rimborsati
Acquista con carta o PayPal
Scarica i documenti tutte le volte che vuoi
Dettagli
SSD
Scienze matematiche e informatiche INF/01 Informatica

I contenuti di questa pagina costituiscono rielaborazioni personali del Publisher fiorixf2 di informazioni apprese con la frequenza delle lezioni di Sistemi operativi e studio autonomo di eventuali libri di riferimento in preparazione dell'esame finale o della tesi. Non devono intendersi come materiale ufficiale dell'università Politecnico di Milano o del prof Silvano Cristina.
Appunti correlati Invia appunti e guadagna

Domande e risposte

Hai bisogno di aiuto?
Chiedi alla community