Lezione 32 Gestione dell'I/O - WEB Lab
←
→
Trascrizione del contenuto della pagina
Se il tuo browser non visualizza correttamente la pagina, ti preghiamo di leggere il contenuto della pagina quaggiù
Lezione 32 Gestione dell'I/O Sistemi Operativi (9 CFU), CdL Informatica, A. A. 2020/2021 Dipartimento di Scienze Fisiche, Informatiche e Matematiche Università di Modena e Reggio Emilia http://weblab.ing.unimo.it/people/andreolini/didattica/sistemi-operativi 1
Quote of the day (Meditate, gente, meditate...) “The key to performance is elegance, not battalions of special cases.” Doug McIlroy (1932-) Matematico, Ingegnere, Programmatore Ideatore del meccanismo “pipe” Ideatore dei filtri UNIX 2
ETEROGENEITÀ DEI DISPOSITIVI 3
Gli ambiti della diversità (Tanti, purtroppo) Un PC moderno è collegato ad una miriade di dispositivi di I/O, fortemente eterogenei sotto diversi punti i vista. Modalità di trasferimento dei dati. Modalità di accesso ai dati. Sincronia, asincronia e isocronia delle operazioni. Velocità di trasferimento. Modalità di programmazione delle richieste e prelievo delle risposte. 4
Modalità di trasferimento dati (A blocchi oppure a caratteri) Per interi blocchi di dati (si parla di periferiche a blocchi). → Tali periferiche possono ospitare un file system (dischi). Per “pacchetti di dati” (periferiche di rete). Per flussi di caratteri (si parla di periferiche a caratteri). → Tutti i rimanenti dispositivi (porte seriali, mouse, tastiere). 5
Modalità di accesso dati (Sequenziale oppure casuale, in lettura e/o scrittura) Sequenziale o diretta (anche detta random). In sola lettura (read-only, CDROM) o in lettura e scrittura (read-write, dischi). 6
Sincronia, asincronia, isocronia (Delle operazioni di I/O) Sincronia. Un dispositivo è detto sincrono se accetta la richiesta successiva solo dopo aver risposto alla precedente (porte seriali standard). Asincronia. Un dispositivo è detto asincrono se accetta molteplici richieste in aniera concorrente, senza dover per forza rispondere subito (dischi rigidi con Native Command Queueing, NCQ). Isocronia. Un dispositivo è detto isocrono se opera ad intervalli di tempo prestabiliti e rigidi (periferiche USB); può essere sincrono o7 asincrono.
Velocità di trasferimento (Da pochi B/s a qualche GB/s) La velocità di trasferimento può variare da alcuni byte al secondo fino a qualche GB al secondo. In generale: i dispositivi a caratteri sono i più lenti (a meno che non operino con la memoria). i dispositivi di rete hanno velocità variabili nell'intervallo medio-alto. i dispositivi a blocchi sono i più veloci. La velocità di trasferimento necessita delll'aggancio a bus opportuni. 8
Bus in uso sui PC attuali (OK, non proprio gli ultimissimi modelli...) 9
TECNICHE PROGRAMMAZIONE I/O 10
Programmazione dell'I/O (Dispositivi diversi traggono beneficio da meccanismi diversi) Programmazione delle richieste. Port Mapped I/O (PIO). Memory Mapped I/O (MMIO). Attesa e ottenimento delle risposte. Busy Waiting. Polling. Direct Memory Access (DMA). Interrupt. Interrupt mitigation. 11
Port Mapped I/O (Scrittura in registri appositi → Impostazione di una operazione di I/O) La programmazione delle porte avviene tramite istruzioni assembly. Ad esempi, su x86 e x86_64: IN → spostamento di un dato da una porta di I/O ad un registro generale. OUT → spostamento i un dato da un registro ad una porta di I/O. Le corrispettive istruzioni INS e OUTS spostano un blocco di dati (stringa). Dispositivi che usano PIO: tastiera, clock interno, USB hub (v1.1). 12
Port Mapped I/O (Specifica degli indirizzi delle porte) L'indirizzo delle porte di I/O può essere specificato in due modi distinti. Uso di una costante: IN AL, 0178h OUT AL, 0178h Uso di un valore contenuto in un registro: MOVL DX, 0178h IN AL, DX OUT AL, DX 13
Port Mapped I/O (Dimensione dei dati) La dimensione del dato è specificata in maniera indiretta, tramite l'uso del registro nel primo operando. IN AL, 0178h → byte (8 bit) IN AX, 0178h → word (16 bit) IN EAX, 0178h → long word (32 bit) Nel caso di trasferimento a 32 bit, l'indirizzo della porta di I/O deve essere allineato a 32 bit. In altre parole, deve essere un multiplo di 4. 14
Memory Mapped I/O (Scrittura in celle di memoria→ Invio dati alla periferica di I/O) I dispositivi fisici utilizzano la memoria centrale come spazio di indirizzi per i registri di stato, di controllo, dei dati. Si usano le solite istruzioni assembly per la modifica dei dati in memoria. INTEL: istruzioni MOV, AND, OR, TEST. I riferimenti alla memoria sono soggetti alle tecniche di protezione degli accessi. INTEL protected mode: accesso in Ring 0. Dispositivi che usano MMIO: scheda audio, USB hub (v2.0), controller SATA, scheda di rete wireless. 15
Busy waiting (La CPU controlla di continuo una condizione segnalante un evento) Si controlla continuativamente che un evento non si verifichi (tipicamente, tramite una variabile che assume un valore). Viene implementato con un ciclo while del tipo while ( !condition ) {}; Metodo usato anche per implementare attese. L'attesa è attiva, ossia avviene a spese della CPU (donde il nome busy waiting). 16
Busy waiting: vantaggi (Estremamente reattivo) L' evento è riconosciuto il più presto possibile. Tecnica utilizzabile anche in quei casi in cui non è previsto nel kernel un meccanismo di notifica del completamento delle operazioni. Tecnica utilizzabile anche in quei casi in cui non è previsto nel kernel un meccanismo di blocco e ripristino per le operazioni lente. 17
Busy waiting: svantaggi (Estremamente dispendioso) La CPU è occupata al 100% nell'attesa. Esempio: si lanci il comando seguente. while [[ ! -a file.txt ]]; do :; done Attesa attiva della creazione di file.txt. Si lanci il comando mpstat 1 per misurare l'utilizzazione di CPU → Una CPU al 100%. Si crei il file file.txt con il comando touch file.txt e l'utilizzazione scende a zero. L'inefficienza aumenta con la durata degli eventi. Non applicabile su sistemi alimentati a batteria. 18
Polling (La CPU controlla periodicamente una condizione segnalante un evento) Si controlla periodicamente che un evento si sia verificato (tipicamente, tramite una variabile che assume un valore). Viene implementato con un ciclo: while while( !condition ) { sleep(timeout) }; A differenza del busy waiting, il controllo è periodico (con frequenza costante oppure no). Fra un controllo ed un altro, la CPU può eseguire tracce di altri processi. → Il polling richiede un meccanismo di blocco 19e ripristino per le operazioni di I/O lente.
Polling: vantaggi (Non così dispendioso come il busy waiting) L'attesa non divora tempo di CPU. Esempio: si lanci il seguente comando. while [[ ! -a file.txt ]], do sleep 10; done Polling della creazione di file.txt con frequenza pari a 0.1 Hz. Si lanci il comando mpstat 1 per misurare l'utilizzazione di CPU → Macchina scarica. Si interrompa il comando con CTRL-C. La CPU può occuparsi d'altro durante l'attesa. 20
Polling: svantaggi (Non così reattivo come il busy waiting) L'evento non è riconosciuto il più presto possibile. Nell'esempio precedente, l'attesa della notifica del file è durata quasi 10 secondi. Inadatto in sistemi con requisiti (quasi) real-time. Richiede un meccanismo di blocco e ripristino dei processi per operazioni di I/O lente. Richiede un po' di risorse di CPU per il controllo periodico (lieve inefficienza). 21
Interruzioni (La CPU si slega dal controllo di ricezione) Obiettivo: liberare la CPU dal controllo dell'avvenuta ricezione del dato. La CPU si lascia segnalare l'avvenuta operazione della periferica stessa, tramite una notifica asincrona (Interrupt Request). A ciascuna specifica notifica viene associata una funzione di gestione di un evento (scadenza timer, ricezione dato) detta Interrupt Service Routine (ISR). 22
Compiti specifici della ISR (Pochi ma fondamentali) Preleva il dato dal buffer della periferica. Controlla il dato (checksum, intestazioni di pacchetti, …). Copia il dato nell'area di memoria preposta a riceverlo. Nel caso, impacchetta il dato in una struttura dati e lo inserisce nelle liste opportune. Abilita le interruzioni sulla CPU. 23
Interruzioni: vantaggi (Migliore efficienza nell'uso della CPU) L'inefficienza legata al controllo del dato scompare. Le interruzioni migliorano il throughput di processi I/O-bound rispetto al busy waiting e al polling. 24
Interruzioni: svantaggi (Non così reattivo come il busy waiting) L'arrivo del dato non è riconosciuto il più presto possibile. Occorre prima eseguire la Interrupt Service Routine. Richiede un meccanismo di blocco e ripristino di operazioni di I/O lente. Richiede un meccanismo di notifiche asincrone di eventi. Richiede un po' di risorse di CPU per l'esecuzione della Interrupt Service Routine (lieve inefficienza).25
Interruzioni: svantaggi (Una ISR deve eseguire velocemente, senza bloccarsi) Eseguono in maniera asincrona, e quini possono interrompere codice critico (altri interruptp handler) → devono essere veloci. Eseguono con l'interruzione in questione disabilitata sulla CPU locale (nel migliore dei casi) o su tutte le CPU (nel peggiore dei casi) → devono essere veloci. Sono time-critical, poiché interagiscono direttamente con l'hardware della macchina. Non possono eseguire in process context, pertanto non si possono bloccare → le operazioni che possono compiere sono limitate. 26
Direct Memory Access (La ISR non deve più manipolare il buffer dati) Il dispositivo è in grado di scrivere sulla memoria centrale del calcolatore. La CPU si svincola dalla procedura di copia dei buffer in memoria centrale. È necessario un ulteriore registro di I/O per la memorizzazione dell'inddirizzo che contiene il dato da leggere o da scrivere. Meccanismo ideale per il trasferimento di buffer grandi. 27
CONTRASTO AL LIVELOCK 28
Il vero punto debole delle interruzioni (Il livelock) Le interruzioni funzionano bene fino a quando il volume di dati prodotti dai dispositivi non aumenta a dismisura. L'aggravio computazionale legato alla gestione della notifica asincrona è alto. Il cuore della ISR esegue ad interruzioni disabilitate sulla CPU → nessuna altra periferica può essere gestita su quella CPU. La ricezione di un dato comporta due context swith: processo → ISR, ISR → processo. Se le interruzioni sono gestite in modalità annidata e con priorità, il kernel continua ad eseguire la ISR. 29
Livelock (La CPU passa tutto il tempo ad eseguire ISR) In tale scenario, il sistema impiega tutto il suo tempo ad eseguire funzioni di gestione (le ISR), e non riesce ad eseguire processi: si ha un livelock. Tratti distintivi del livelock: macchina piantata, incapace di reagire agli stimoli dell'utente (il mouse non funziona, il video è congelato, i processi non avanzano). Spesso, il livelock è causato da un disco oberato di richieste (il LED del disco è costantemente rosso). 30
Contrasto al livelock (Si spezza la ISR in due funzioni: una esegue subito, l'altra successivamente) L'idea vincente per contrastare il livelock è quella di spezzare le operazioni della ISR in due parti: top half e bottom half. Top Half (la ISR vera e propria): esegue l'ACK della Interrupt Request. prepara un buffer dati e lo accoda in una coda speciale associata alla IRQ. schedula l'esecuzione in differita (deferred execution) di una procedura di gestione del dato recuperato. abilita le interruzioni sulla CPU ed esce. opera in Interrupt Context. 31
Contrasto al livelock (Si spezza la ISR in due funzioni: una esegue subito, l'altra successivamente) L'idea vincente per contrastare il livelock è quella di spezzare le operazioni della ISR in due parti: top half e bottom half. Bottom Half (la funzione di gestione): schedulata dalla top half per l'esecuzione in differita (in un istante in cui il carico di lavoro sarà più basso). opera ad interruzioni abilitate (l'arrivo di una Interrupt Request può bloccarla). opera sul buffer dati preparato dalla top half (copia in user space, inserimento in liste, …). 32 opera in Kernel o Process Context.
Perché la separazione è vincente? (Le interruzioni sono spente per il più breve tempo possibile) Rendendo breve la top half, le interruzioni sono abilitate nuovamente nel più breve tempo possibile. → I dispositivi possono “sparare” dati alla velocità più elevata possibile. Non appena finisce la “tempesta” di interruzioni, il kernel elabora e consegna i buffer dati alle applicazioni. 33
Quando top e quando bottom (Come suddividere le funzionalità di un gestore delle interruzioni) Non esiste una ricetta univoca per scegliere quali operazioni di gestione della interruzione vadano gestite da top e quali da bottom half. In generale, una funzione va eseguita nella top half: se è time-sensitive. se opera direttamente con l'hardware. se non svolge compiti che richiedono il blocco (ad esempio, allocazione di memoria “con blocco”). Tutto il resto va eseguito nella bottom half. 34
Bottom half in Linux (Una evoluzione lunga e dolorosa) Il kernel Linux implementa lo schema di gestione basato su top half e bottom half. Esistono diverse implementazioni di bottom half, risultato di anni e anni di tentativi, errori, riscritture da zero, … Bottom half originarie (BH), Task queue. Softirq, tasklet. Work queue. Threaded Interrupt Handler. Le bottom half sono eseguite ad IRQ abilitate. 35
La bottom half originaria (Non scala con il numero di CPU) Adoperata In Linux ≤v2.2. Array di 32 distinti puntatori a funzioni di gestione (dischi, timer, tastiere, …). Le funzioni eseguono in Interrupt Context; non possono bloccarsi e non si può rischedulare un altro processo (non esiste un PCB della traccia che esegue l'ISR). Non si può invocare la schedule(). Locking molto rozzo: può eseguire una sola BH alla volta, indipendentemente dal numero di CPU. → Problema: non scala col numero di CPU. Meccanismo rimosso nel kernel 2.5. 36
Task Queue (Inefficiente in presenza di periferiche molto veloci) Introdotta nella versione v2.2 del kernel. La task queue è una coda di strutture rappresentanti funzioni a invocare (estensione dinamica delle BH). Le funzioni eseguono in Interrupt Context e non possono bloccarsi (no schedule()). Le funzioni sono inserite nella lista e sono eseguite una dopo l'altra in occasioni ben definite (a seconda del tipo di coda): termine di una top half. scadere di un timer. Meccanismo rimosso nel kernel 2.3 poiché il driver 37 Ethernet non scalava con il numero di CPU.
Task Queue (Diagramma semplificato) 38
Softirq (Possono eseguire concorrentemente su diverse CPU) Nel kernel v2.3 sono state introdotte le softirq, che hanno rimpiazzato il meccanismo delle BH. Array di 32 distinti puntatori a funzioni di gestione delle bottom half (definiti staticamente dai programmatori). Le softirq eseguono in Interrupt Context (no schedule()); un processo server generato dal kernel (ksoftirqd/n) esegue le funzioni su ogni CPU. Una softirq schedulata su una CPU esegue su quella CPU. Le softirq (anche uguali) possono essere eseguite concorrentemente su una qualunque CPU. 39
Tasklet (Simili alle softirq; possono essere migrate su CPU diverse) Nel kernel v2.3 sono state introdotte anche le tasklet. Le tasklet usano l'infrastruttura delle softirq per implementare una coda dinamica di funzioni schedulabili Le tasklet eseguono in Interrupt Context (no schedule()). A differenza delle softirq, le tasklet possono eseguire su una CPU diversa da quella che le ha schedulate (miglior balancing). Le tasklet (purché diverse) possono eseguire concorrentemente su CPU diverse. Tasklet e softirq coesistono. 40
Workqueue (Possono essere interrotte e ripristinate, migliorando la latenza dei processi) Nella versione v2.6 del kernel sono state introdotte le work queue. Una work queue è una coda dinamica di funzioni schedulabili, destinata a rimpiazzare le tasklet. A differenza delle tasklet, la work queue esegue in Process Context. Il kernel crea un processo server con un PCB (dal nome events/n), che esegue tutte le funzioni della work queue assegnata alla CPU. A differenza di un processo ordinario, la work queue non può accedere allo user address space. Tale processo può essere rischedulato, poiché ha un proprio PCB (si può usare schedule() nelle funzioni 41 dentro la bottom half ).
Threaded Interrupt Handler (Si può modificare dinamicamente la priorità della BH) Le tasklet possono provocare problemi di starvation ai processi applicativi (eseguono a priorità più alta). Le funzioni delle work queue sono gestite da un processo server per CPU → possibili alte latenze per le funzioni in coda. → Devastante nei sistemi real-time. Nei kernel attuali, i processi di controllo di softirq, tasklet e work queue generano un processo in Kernel Context per ciascuna funzione da eseguire. Si può modificare la priorità del processo (per favorire alcune interruzioni rispetto ad altre). 42
ACCESSO UNIFICATO AI DISPOSITIVI 43
I protagonisti del sistema di I/O (Dispositivo, bus, device driver) Chi sono i protagonisti? Il dispositivo fisico (a blocchi, a caratteri, di rete). Il bus a cui il dispositivo è attaccato. Il software che gestisce il dispositivo. Tutti questi componenti hardware e software devono essere gestiti in maniera uniforme. Ricordate il motto: uno scheletro di codice che invoca diverse funzionalità particolari a ciascun dispositivo. 44
Device driver (Il software di gestione del dispositivo) Il device driver (pilota del dispositivo) è un componente software del kernel che gestisce un dispositivo a basso livello. Accende/spegne il dispositivo. Attacca il dispositivo al sistema. Esegue operazioni di controllo sul dispositivo. Riceve le richieste dal file system e le traduce nelle richieste al dispositivo. Recupera le risposte dal dispositivo. 45
Una periferica, più driver (Un male necessario) Ciascun device driver deve essere compatibile con il sottosistema di I/O del kernel. Tuttavia: kernel diversi adottano strategie diverse di comunicazione fra i diversi componenti del sottosistema di I/O. kernel diversi possono essere eseguiti su architetture hardware diverse. → Per lo stesso dispositivo esistono più device driver in circolazione, uno per ogni coppia (kernel, architetura hardware) possibile. 46
Un driver, più periferiche (Tipico nei sistemi UNIX) Lo stesso device driver può gestire una classe di dispositivi simili. Una serie di schede di rete dello stesso produttore. Dischi rigidi con caratteristiche simili. Schede seriali standard (UART). Chiavette USB. ... 47
Una visione unificata dell'I/O (Uno scheletro, n implementazioni) Il kernel definisce delle classi di dispositivi idealizzate. Disco, schermo, stampante, nastro, rete, … Le classi sono implementate da componenti generali, detti gestori, che definiscono il comportamento atteso di un dispositivo di un dato tipo, ovvero l'interfaccia d'uso. Tutti i device driver devono aderire all'interfaccia del relativo gestore. I driver implementano il comportamento atteso (in 48 sostanza, i dettagli).
Gli “utenti” delle classi di dispositivi (Alcuni esempi significativi) ls mkfs oracle10 hdparm firefox User Chiamate Mode di sistema Kernel Mode Virtual File System File System Accesso Networking (operazioni su per Raw Controllo (connessione, invio e I/O dispositivo file e directory) blocchi ricezione messaggi) EXT4 NTFS ISO9660 Disco Schermo Seriale PPP TCP/IP X.25 Block I/O Data Link Provider Interfaccia di accesso ai device driver Disk CD Tape Display Comm. Wireless Ethernet 49 drivers drivers drivers drivers drivers drivers drivers
Gli “utenti” delle classi di dispositivi (Alcuni esempi significativi) ls mkfs oracle10 hdparm firefox User Chiamate Mode di sistema Il processo ls accede ai metadatiKernel di Mode file e directory, in maniera strutturata. Virtual File System Il VFS individua il tipo di file system File System Accesso corretto, che a sua Networking volta effettua (operazioni su per Raw Controllo (connessione, invio e I/O richieste al dispositivo. dispositivo Il gestore della file e directory) blocchi ricezione messaggi) classe di dispositivi a blocchi “Block EXT4 NTFS ISO9660 Disco Schermo Seriale ottimizza I/O” trasforma, PPP TCP/IP ed inviaX.25al Block I/O device driver opportuno le richieste Data Link Provider del FS. Le risposte sono mantenute in cache. Interfaccia di accesso ai device driver Disk CD Tape Display Comm. Wireless Ethernet 50 drivers drivers drivers drivers drivers drivers drivers
Gli “utenti” delle classi di dispositivi (Alcuni esempi significativi) ls mkfs oracle10 hdparm firefox User Chiamate Mode di sistema Kernel Il processo mkfs accede al disco Mode attraverso Virtual File System un file speciale File System Accesso (/dev/sda1). L'accesso a tale file Networking Raw Controllo (operazioni su per I/O permette di leggere dispositivo e scrivere (connessione, invio e il file e directory) blocchi dispositivo (qui, ricezione messaggi) una partizione) EXT4 NTFS ISO9660 Disco per blocchi, Schermo Seriale saltando PPP ilTCP/IP file system. X.25 In tal modo è possibile, per Block I/O esempio, preparareData il Link fileProvider system perail'uso Interfaccia di accesso device(creazione driver inode). Disk CD Tape Display Comm. Wireless Ethernet 51 drivers drivers drivers drivers drivers drivers drivers
Gli “utenti” delle classi di dispositivi (Alcuni esempi significativi) ls mkfs oracle10 hdparm firefox User Chiamate Mode di sistema Kernel Il processo oracle10 è un Mode database. Esso apre il file speciale Virtual File System File System Accesso della partizione /dev/sda1 Networking in Raw Controllo (operazioni su per I/O modalità “raw I/O”; dispositivo non invio (connessione, vienee file e directory) blocchi usato il file system ricezione e nonmessaggi) sono EXT4 NTFS ISO9660 Disco mantenute Schermo Seriale in cache PPP le risposte. TCP/IP X.25 L'organizzazione dei dati e il Block I/O caching delle risposte Data Link Provider sono a carico Interfaccia di accesso dell'applicazione. ai device driver Disk CD Tape Display Comm. Wireless Ethernet 52 drivers drivers drivers drivers drivers drivers drivers
Gli “utenti” delle classi di dispositivi (Alcuni esempi significativi) ls mkfs oracle10 hdparm firefox User Chiamate Mode di sistema Kernel Mode Virtual File System File System Accesso Networking (operazioni su per Raw Controllo (connessione, invio e I/O dispositivo file e directory) blocchi ricezione messaggi) EXT4 NTFS ISO9660 Disco Schermo Seriale PPP TCP/IP X.25 Block I/O Data Link Provider Interfaccia di accesso ai device driver Disk CD Tape Display Comm. Wireless Ethernet 53 drivers drivers drivers drivers drivers drivers drivers
Gli “utenti” delle classi di dispositivi (Alcuni esempi significativi) ls mkfs oracle10 hdparm firefox User Chiamate Mode di sistema Kernel Mode Virtual File System File System Accesso Networking (operazioni su per Raw Controllo (connessione, invio e I/O dispositivo file e directory) blocchi ricezione messaggi) EXT4 NTFS ISO9660 Disco Schermo Seriale PPP TCP/IP X.25 Block I/O Data Link Provider Interfaccia di accesso ai device driver Disk CD Tape Display Comm. Wireless Ethernet 54 drivers drivers drivers drivers drivers drivers drivers
Gli “utenti” delle classi di dispositivi (Alcuni esempi significativi) ls mkfs oracle10 hdparm firefox User Chiamate Mode di sistema Kernel Mode Virtual File System File System Accesso Networking (operazioni su per Raw Controllo (connessione, invio e I/O dispositivo file e directory) blocchi ricezione messaggi) EXT4 NTFS ISO9660 Disco Schermo Seriale PPP TCP/IP X.25 Block I/O Data Link Provider Interfaccia di accesso ai device driver Disk CD Tape Display Comm. Wireless Ethernet 55 drivers drivers drivers drivers drivers drivers drivers
Gli “utenti” delle classi di dispositivi (Alcuni esempi significativi) ls mkfs oracle10 hdparm firefox User Chiamate Mode di sistema Kernel Mode Virtual File System File System Accesso Networking (operazioni su per Raw Controllo (connessione, invio e I/O dispositivo file e directory) blocchi ricezione messaggi) EXT4 NTFS ISO9660 Disco Schermo Seriale PPP TCP/IP X.25 Block I/O Data Link Provider Interfaccia di accesso ai device driver Disk CD Tape Display Comm. Wireless Ethernet 56 drivers drivers drivers drivers drivers drivers drivers
“Implementare tutti i dettagli?” (Che cosa significa?) Il device driver: mappa le operazioni standard delle classi nelle operazioni particolari del dispositivo. legge lo stato interno del dispositivo e lo traduce in una descrizione generale da fornire al gestore della classe, usabile nello “scheletro unico” di codice (VFS, gestore a blocchi). nasconde i comportamenti non rilevanti per gli utenti (ad es., i tentativi di posizionamento della testina di un CD- ROM). coordina l'interazione fra dispositivo ed applicazione (blocca l'applicazione se il dato è da leggere, la ripristina 57 se il dato è arrivato).
“Implementare tutti i dettagli?” (Che cosa significa?) Il device driver incapsula, nel suo codice, tutti i dettagli di accesso ottimizzato al dispositivo. Per esempio, ad un disco conviene leggere un dato quando è vicino alla testina. Il device driver incapsula, nel suo codice, tutti i dettagli di gestione degli errori. Come gestire gli errori recuperabili (i noti riposizionamenti della testina del CD-ROM). L'applicazione non deve preoccuparsi di essi (al limite, subisce un ritardo nei tempi di risposta). 58
Distribuzione dei device driver (Scrittura, test, distribuzione sotto forma di modulo user o kernel) Prima di essere incluso in una distribuzione software, un driver è soggetto a test rigorosi. Funzionali, prestazionali, di sicurezza. Tuttavia, spesso i device driver sono distribuiti separatamente dal kernel (ad esempio, quando sono scritti da terze parti). Per tale motivo, i kernel moderni permettono ai driver di essere inseriti a mo' di “plugin”. Esecuzione in user mode. Esecuzione in kernel mode, sottoforma di “moduli” attivabili a tempo di esecuzione. 59
UNIX: istanze dispositivi e file speciali (Un dispositivo, più file speciali) Come fare a distinguere due istanze di periferiche appartenenti alla stessa classe? Due dischi SATA distinti. Un CD e un CD-RW. Quattro partizioni distinte sullo stesso disco. Si associa a ciascun dispositivo un file speciale, contenuto nella directory /dev. ls -l /dev/sda*, /dev/tty{1,2} Tipo: carattere (c) o blocchi (b). Major: identificativo del tipo di dispositivo. 60 Minor: identificativo dell'istanza di dispositivo.
UNIX: accesso ai dispositivi (Tramite un file speciale) L'apertura di un file speciale ritorna un descrittore di file aperto. Il descrittore del file punta ad una struct file_operations contenente le funzioni per: la lettura/scrittura dei singoli blocchi o di un flusso di caratteri dal/sul dispositivo. l'eventuale riposizionamento dell'offset. controllare il dispositivo. L'interfaccia di accesso è uniforme. Il device driver implementa le funzionalità offerte dalla struttura.61
Creazione di file speciali (Comando mknod) In passato: veniva svolta a mano, tramite il comando mknod. mknod /dev/tty2 c 4 2 bisognava conoscere (o, peggio, assegnare senza creare conflitti) major e minor del dispositivo. Oggi: svolta in automatico, tramite il processo server di sistema udev. udev riceve dal kernel messaggi riguardanti l'inserimento e la rimozione di dispositivi. → udev crea e rimuove file speciali. 62
UNIX: dispositivi a blocchi (Disco: file speciale /dev/sda) Dispositivi a blocchi: usati per contenere file system. Su dispositivi ad accesso random. Gestione di più richieste concorrenti. Stretta collaborazione con il gestore della memoria virtuale (si interpella il disco se il dato non è già nella cache centrale). Accesso tramite apertura di un file speciale a blocchi. Per un disco rigido: /dev/sda, /dev/sda1 63 strings -a /dev/sda1
UNIX: dispositivi a caratteri (Disco: file speciale /dev/sda) Dispositivi a caratteri: tutti i dispositivi che non sono in grado di contenere un file system. Possono essere strutturati per flussi (porta seriale) o per record logici (mouse). Possono fornire accesso solo sequenziale (porta seriale, modem seriale) oppure anche random (frame buffer). Accesso tramite apertura di un file speciale a caratteri. Per un terminale testuale: /dev/tty1, /dev/vcs1 echo “testo” > /dev/vcs1 cat < /dev/vcs1 64
UNIX: dispositivi di rete (Nessun file speciale; invece, si usa una API) Dispositivi di rete (Ethernet, Wireless): non sono acceduti tramite l'apertura di un file speciale. Configurazione e controllo: strumenti di rete (ifconfig, route, …). Letture e risposte: socket API (connect(), bind(), listen(), accept(), sendmsg() o write(), recvmsg() o read(), shutdown() o close()) Una connessione remota è identificata ancora da un descrittore di file! Vedrete tutto questo nei corsi successivi, non qui. 65
Interfaccia unificata di accesso ai driver (Tramite puntatori a funzioni raccolti in strutture dati) Ciascun device driver è acceduto in maniera unificata, attraverso puntatori a funzioni ben precise (implementate nei driver stessi). Chi invoca le funzioni del device driver? Direttamente il VFS, in caso di dispositivo unico, non appartenente a nessuna classe. Altrimenti, il componente gestore della classe di dispositivi di cui fa parte il driver. Il gestore accede al driver per due motivi. Per conto di una chiamata di sistema. Per aggiornare lo stato del dispositivo nel contesto della classe di cui fa parte. 66
I gestori di base dei dispositivi in Linux (Diagramma semplificato) Chiamate di sistema Char ALSA Frame V4L TTY Block driver core buffer core core layer core ALSA Frame V4L TTY Serial Block SCSI driver buffer driver driver core driver core driver Serial libata USB I gestori delle classi di dispositivi sono gli driver storage “scheletri unici” che contattano i device driver. SATA driver 67
Quali funzioni esporta il device driver? (Driver a caratteri semplice in nessuna classe di dispositivi) /dev/mem: memoria dell'intero sistema. Questo dispositivo a caratteri esporta una interfaccia di (poche) funzioni contenuta in una struct file_operations. http://lxr.linux.no/#linux+v3.6.5/drivers/char/mem.c#L745 L'applicazione invoca la read() da /dev/mem; il VFS invoca direttamente read_mem(). 68
Quali funzioni esporta il device driver? (Driver a caratteri appartenente ad una classe di dispositivi) /dev/fb0: frame buffer. Il frame buffer è un'area di memoria in cui viene “disegnato” uno schermo. Questo dispositivo è molto complesso. Impostazione della risoluzione video e dei colori, disegno di un cursore, … Di frame buffer ne possono esistere tanti (dual screen, X11, console testuali, …). Ogni scheda video ha i suoi dettagli implementativi. La struct file_operations non è in grado di descrivere tutti questi scenari. 69
Quali funzioni esporta il device driver? (Driver a caratteri appartenente ad una classe di dispositivi) Ogni frame buffer device driver esporta una interfaccia di funzioni contenuta in una struct fb_ops. http://lxr.linux.no/#linux+v3.6.5/include/linux/fb.h#L633 fb_open(), fb_read(), fb_cursor(), … Il gestore “frame buffer core” fornisce una astrazione unificata di ciascuna istanza di dispositivo frame buffer in esecuzione. Usa una struct fb_info, preparata dal device driver in fase di inizializzazione. http://lxr.linux.no/#linux+v3.6.5/include/linux/fb.h#L844 La struct fb_info contiene un puntatore alla struct fb_ops del device driver relativo. 70
Quali funzioni esporta il device driver? (Driver a caratteri appartenente ad una classe di dispositivi) L'applicazione (server grafico) invoca una operazione su /dev/fb0. ioctl() è un “salvagente” che permette di invocare tutte quelle operazioni altrimenti non esprimbiili in termini di read(), write(), seek(), … La struct file_operations per i dispositivi di tipo frame buffer è definita qui: http://lxr.linux.no/#linux+v3.6.5/drivers/video/fbmem.c#L1480 La read() su /dev/fb0 si trasforma in una invocazione di fb_read(). 71
Quali funzioni esporta il device driver? (Driver a caratteri appartenente ad una classe di dispositivi) La fb_read() è definita qui: http://lxr.linux.no/#linux+v3.6.5/drivers/video/fbmem.c#L740 Identifica la struct fb_info dell'istanza di frame buffer in esecuzione. Invoca il metodo fb_read() della struct fb_ops puntata dalla struct fb_info. 72
Quali funzioni esporta il device driver? (Driver a blocchi gestito dal block layer) Il block layer: individua le pagine di memoria coinvolte nella richiesta. Se le pagine sono già in memoria, le ritorna. Altrimenti, programma una lettura in avanti (readahead) di 128KB. traduce le richieste di pagine in “richieste generiche” di I/O. traduce le richieste generiche di I/O in richieste al dispositivo. sottomette le richieste al dispositivo. 73
Quali funzioni esporta il device driver? (Driver a blocchi gestito dal block layer) Ciascun dispositivo a blocchi esporta una interfaccia di funzioni contenuta in una struttura dati di tipo struct block_device_operations. http://lxr.linux.no/#linux+v3.6.5/include/linux/blkdev.h#1406 Definisce come aprire, chiudere, controllare (ioctl()) ed accedere direttamente ad un settore del dispositivo. Ad esempio, per un disco SATA/SCSI: http://lxr.linux.no/#linux+v3.6.5/drivers/scsi/sd.c#L1338 74
Quali funzioni esporta il device driver? (Driver a blocchi gestito dal block layer) Se l'accesso avviene tramite il file system, il VFS usa le funzioni contenute nelle struct file_operations che il file system definisce per file e directory. Ad esempio, per il file system EXT2: Directory http://lxr.linux.no/#linux+v3.6.5/fs/ext2/dir.c#L724 File http://lxr.linux.no/#linux+v3.6.5/fs/ext2/file.c#L63 75
Quali funzioni esporta il device driver? (Driver a blocchi gestito dal block layer) Se l'accesso avviene tramite file speciale (/dev/sda), il VFS usa le funzioni contenute nella struct file_operations fornita dal block layer. http://lxr.linux.no/#linux+v3.6.5/fs/block_dev.c#L1624 In entrambi i casi (accesso via file system o via file speciale), la lettura dei dati avviene tramite la funzione do_sync_read(). 76
Puoi anche leggere