torna a frapec
torna all'elenco delle dispense
La CPU invia un documento da stampare nel buffer di memoria della periferica. Mentre la stampante riproduce il documento, la CPU potrebbe interrogare continuamente lo stato del dispositivo, per riconoscere il momento in cui questo ha terminato di stampare i dati presenti nella memoria e quindi è pronto per ricevere un altro blocco di dati da stampare.
Questa interrogazione dello stato del dispositivo, per verificare la sua disponibilità a comunicare, è detta tecnica del Polling.
Si ha una migliore utilizzazione della CPU se la si impegna nello svolgimento dei compiti cui è preposta, e si fa in modo che venga avvertita dall'esterno, cioè tramite un segnale applicato su una linea del control bus, del verificarsi di un evento, in conseguenza del quale deve produrre determinate azioni. Sarà solo in questo momento che la CPU sospenderà temporaneamente il suo lavoro e tratterà l'evento.
La linea adibita ad avvertire la CPU che si è verificato un evento esterno è indicata con Interrupt Request (INTR), ed è pilotata dal dispositivo.
L'unità di esecuzione, come rete sequenziale interna alla CPU, attraversa ciclicamente due fasi: preleva un'istruzione dalla coda alimentata dalla BIU e la esegue. Un programma può essere sospeso, per servire una richiesta di interruzione, solo al termine dell'esecuzione completa di un'istruzione. Il campionamento della linea INTR, al termine dell'esecuzione, non comporta alcun rallentamento nelle operazioni della CPU, in quanto esso agisce come deviatore delle transizioni dell'EU.
Si supponga che, mentre la CPU esegue un programma, un dispositivo esterno, mediante un interruttore, indica che si è verificato un caso per il quale è richiesto l'intervento della CPU. Potrebbe essere, ad esempio, una stampante che segnala lo svuotamento del buffer di stampa e quindi le azioni richieste alla CPU consistono nell'inviare un altro blocco di dati da stampare; oppure potrebbe trattarsi di un'unità a disco che segnala che il settore indirizzato è stato raggiunto e il dato richiesto è disponibile, e la CPU deve attivare la procedura di lettura. In definitiva le operazioni che la CPU deve compiere in seguito ad una richiesta di interruzione dipendono dal tipo di periferica e sono descritte in un apposito sottoprogramma di servizio delle interruzioni (driver). Un segnale di interruzione ha lo stesso effetto di un'istruzione di chiamata di funzione, ma mentre l'istruzione CALL si trova in un punto fisso del programma (quindi si conosce il punto in cui il programma principale verrà sospeso), l'interruzione può presentarsi in un momento imprevedibile.
Quindi prima di eseguire il programma di servizio delle interruzioni, la CPU, deve attraversare una fase di predisposizione al servizio, simile alle operazioni associate all'esecuzione di un'istruzione CALL; al termine di questa fase, l'EU esegue il programma di servizio, richiesto dal dispositivo esterno, nella normale sequenza di prelievo, ed esecuzione.
Talvolta può risultare necessario che la CPU non venga distolta dal suo lavoro; ovvero se giungesse un'interruzione, si potrebbero compromettere i risultati di un'elaborazione critica. Si ha la possibilità di rendere la CPU insensibile alle richieste di interruzione eseguendo, prima della fase critica, l'istruzione CLI (Clear Interrupt enable flag). Terminata la fase critica, la CPU ritorna nella condizione di accettare le interruzioni mediante l'esecuzione dell'istruzione STI (Set Interrupt enable flag). Queste due istruzioni agiscono SETtando o RESETtando un flip flop, detto appunto flag di abilitazione delle interruzioni, la cui uscita Q agisce da segnale di abilitazione, verso l'unità di controllo, per la linea INTR; in altri termini la flag di interruzione, posta a zero, 'nasconde' o 'maschera' le interruzioni che giungono alla CPU tramite il segnale INTR.
Si pensi, ad esempio, ad una applicazione di magazzino che, durante le operazioni di vendita o di rifornimento della merce, deve aggiornare costantemente la quantità di prodotti presenti in deposito. Ad esempio quando si vende un oggetto, la procedura dovrebbe prevedere l'aggiornamento del numero di articoli rimasti. Questa operazione è composta dalle seguenti istruzioni:
Leggi la quantità disponibile in magazzino sottrai, da questo valore, il numero di articoli venduti memorizza il risultato
Se ci sono due processi associati allo stesso programma, ovvero due punti vendita, potrebbe verificarsi che due clienti acquistino contemporaneamente lo stesso prodotto. Il caso indesiderato che si deve prevenire è il seguente: Uno dei due processi esegue la prima istruzione, poi si verifica l'interruzione generata dal timer, che segnala la scadenza del quanto di tempo assegnato al processo. A questo punto il sistema operativo cede l'uso della CPU al secondo processo, che svolge le tre operazioni aggiornando la quantità di oggetti presenti in magazzino. Quando il processo interrotto ritorna in esecuzione usa il valore della variabile che aveva letto prima dell'interruzione, che non è più valido. In questo caso, le tre operazioni devono essere eseguite in forma indivisibile: si devono disabilitare le interruzioni prima di entrare nella sezione critica e si devono abilitare al termine della sezione critica.
Così come l'istruzione CALL specifica l'indirizzo della funzione da eseguire, così la periferica, accanto al segnale INTR, deve fornire sul data bus un codice, che la CPU, quando lo preleva, usa per determinare la periferica che ha emesso l'interruzione ossia per richiamare l'opportuna funzione da eseguire.
La linea INTR della CPU non è pilotata direttamente dalle periferiche, ma dal componente 8259 PIC (Programmable Interrupt Controller), che la CPU tratta come dispositivo di I/O, il cui compito principale è di gestire le richieste provenienti da, al massimo, otto periferiche, e di comunicare, sul data bus, il codice associato all'INTR, detto tipo di interruzione, o vettore di interruzione.
In fase di avvio, il sistema operativo carica in memoria i driver delle periferiche e memorizza l'indirizzo di memoria in cui è stato memorizzato il driver, in uno degli elementi di una tabella che si trova in una posizione convenzionale in memoria. Si potrebbe avere, ad esempio:
offset | Puntatore |
0 | CS:IP del driver 1 |
4 | CS:IP del driver 2 |
8 | CS:IP del driver 3 |
… | … |
Una periferica emette la richiesta di interruzione su una delle linee IRQ del controllore. Il controllore la comunica alla CPU. Quando la CPU sente l'interruzione:
salva la coppia CS:IP sullo stack
genera il segnale INTA (Interrupt Acknowledge) verso il PIC
il PIC comunica il tipo di interruzione sul data bus, ad esempio 2 perchè la periferica era collegata sulla linea IRQ2.
La CPU moltiplica il tipo di interruzione per 4 (la lunghezza in byte di un puntatore) e ottiene l'offset per accedere alla tabella, in questo caso 8.
La CPU deposita l'offset (8) sull'address bus e preleva dalla memoria il dato di 32 bit: 16 bit verranno trasferiti nel registro CS e gli altri 16 nel registro IP.
A questo punto l'esecuzione procede dalla locazione CS:IP, ovvero la CPU esegue il programma di gestione della periferica.
Si deve notare che si è realizzato un modo di accesso indiretto al programma di gestione della periferica, cioè, la periferica comunica un numero che rappresenta l'offset di una locazione che, a sua volta, specifica l'indirizzo del programma da richiamare.
Nella CPU '86 le prime posizioni della tabella sono riservate per determinate interruzioni:
posizione 0: puntatore al programma di servizio per l'interruzione "Errore di divisione" (generata internamente alla CPU e non da un dispositivo),
posizione 1: puntatore al programma per la gestione in "single step" dei programmi,
posizione 2: puntatore al programma per il trattamento delle interruzioni non mascherabili,
posizione 4: puntatore al programma per il trattamento dell'overflow, richiesto tramite l'istruzione INTO,
e via via si troveranno poi i puntatori ai sottoprogrammi di servizio delle varie periferiche (video, tastiera ecc...). Il tipo di interruzione comunicato alla CPU, tramite le linee D0-D7 del data bus, è l'indice per accedere alla tabella dei puntatori.
L'ultima istruzione del programma di servizio dell'interruzione è IRET (Interrupt Return), che serve a recuperare dallo stack l'indirizzo da cui riprendere ad eseguire il programma interrotto.
La linea RESET è una linea di interrupt a priorità maggiore, che forza la CPU a portare i registri nei seguenti stati:
Flag: tutte azzerate
Instruction Pointer: 0000
registro CS: FFFF
registro DS: 0000
registro SS: 0000
registro ES: 0000
coda istruzioni: vuota.
Dopo un reset, cioè, la CPU esegue il programma che inizia dalla locazione fisica FFFF0, questo programma passa il controllo dell'elaboratore al sistema operativo.