it-swarm.it

Come viene gestito un interrupt in Linux?

So solo che Interrupt è un hardware signal assertion causato in un pin del processore. Ma vorrei sapere come lo gestisce il sistema operativo Linux.
Quali sono tutte le cose che accadono quando si verifica un interrupt?

35
Sen

Ecco una visione di alto livello dell'elaborazione di basso livello. Sto descrivendo una semplice architettura tipica, le architetture reali possono essere più complesse o differire in modi che non contano a questo livello di dettaglio.

Quando si verifica un interrupt , il processore osserva se gli interrupt sono mascherati. Se lo sono, non accade nulla finché non vengono smascherati. Quando gli interrupt vengono smascherati, se ci sono interruzioni in sospeso, il processore ne sceglie uno.

Quindi il processore esegue l'interruzione ramificando un determinato indirizzo in memoria. Il codice a quell'indirizzo è chiamato interrupt handler . Quando il processore si dirama lì, maschera gli interrupt (quindi il gestore di interrupt ha il controllo esclusivo) e salva il contenuto di alcuni registri in un punto (in genere altri registri).

Il gestore di interrupt fa ciò che deve fare, in genere comunicando con la periferica che ha attivato l'interrupt per inviare o ricevere dati. Se l'interruzione è stata generata dal timer, il gestore potrebbe attivare lo scheduler del sistema operativo, per passare a un thread diverso. Quando il gestore termina l'esecuzione, esegue una speciale istruzione return-from-interrupt che ripristina i registri salvati e smaschera gli interrupt.

Il gestore di interrupt deve essere eseguito rapidamente, poiché impedisce l'esecuzione di qualsiasi altro interrupt. Nel kernel di Linux, l'elaborazione degli interrupt è divisa in due parti:

  • La "metà superiore" è il gestore di interrupt. Fa il minimo necessario, in genere comunica con l'hardware e imposta un flag da qualche parte nella memoria del kernel.
  • La "metà inferiore" esegue qualsiasi altra elaborazione necessaria, ad esempio copiando i dati nella memoria di processo, aggiornando le strutture dei dati del kernel, ecc. Può richiedere del tempo e persino bloccare l'attesa di un'altra parte del sistema poiché viene eseguita con gli interrupt abilitati.

Come al solito su questo argomento, per ulteriori informazioni, leggere Linux Device Driver ; capitolo 1 riguarda gli interrupt.

Gilles già descritto il caso generale di un interrupt, quanto segue si applica specificamente a Linux 2.6 su un'architettura Intel (parte di questo si basa anche sulle specifiche Intel).

Un interrupt è un evento che modifica la sequenza di istruzioni eseguite dal processore.
Esistono due diversi tipi di interrupt:

  • Interruzione sincrona (eccezione) prodotta dalla CPU durante l'elaborazione delle istruzioni
  • Interruzione asincrona (Interruzione) emessa da altri dispositivi hardware

Le eccezioni sono causate da errori di programmazione (fe Errore di divisione, Errore di pagina, Overflow) che devono essere gestiti dal kernel . Invia un segnale al programma e tenta di recuperare dall'errore.

Sono classificate le seguenti due eccezioni:

  • Eccezione rilevata dal processore generata dalla CPU durante il rilevamento di una condizione anomala; diviso in tre gruppi: Difetti generalmente possono essere corretti, Trappole segnalare un'esecuzione, Interrompi sono errori gravi.
  • Eccezione programmata richiesta dal programmatore, gestita come una trappola.

Gli interrupt possono essere emessi da dispositivi I/O (tastiera, scheda di rete, ..), timer di intervallo e (su sistemi multiprocessore) altre CPU. Quando si verifica un interrupt, la CPU deve interrompere le sue istruzioni correnti ed eseguire l'interrupt appena arrivato. Deve salvare il vecchio stato del processo interrotto per (probabilmente) riprenderlo dopo che l'interrupt è stato gestito.

La gestione degli interrupt è un'attività delicata:

  • Gli interruzioni possono verificarsi in qualsiasi momento, il kernel cerca di toglierlo il più presto possibile
  • Un interrupt può essere interrotto da un altro interrupt
  • Ci sono regioni nel kernel che non devono assolutamente essere interrotte

Sono definiti due diversi livelli di interrupt:

  • Interrupt mascherabili emessi da dispositivi I/O; può essere in due stati, mascherato o non mascherato. Vengono elaborati solo gli interrupt non mascherati.
  • Interrupt non mascherabili ; malfunzionamenti critici (ad es. guasto hardware); elaborato sempre dalla CPU.

Ogni dispositivo hardware ha la sua linea IRQ (Interrupt Request). Gli IRQ sono numerati a partire da 0. Tutte le linee IRQ sono collegate a un programmable interrupt controller (PIC). Il PIC ascolta gli IRQ e li assegna alla CPU. È anche possibile disabilitare una linea IRQ specifica.
I moderni sistemi Linux multiprocessing generalmente includono il più recente Advanced PIC (APIC), che distribuisce le richieste IRQ equamente tra le CPU.

Il passaggio intermedio tra un interrupt o un'eccezione e la sua gestione è la tabella descrittore di interrupt (IDT). Questa tabella associa ogni vettore di interrupt o eccezione (un numero) a un gestore specificato (ad es. Errore di divisione viene gestito dalla funzione divide_error()).

Attraverso l'IDT, il kernel sa esattamente come gestire l'interrupt o l'eccezione verificatisi.


Quindi, cosa fa il kernel quando si verifica un interrupt?

  • La CPU verifica dopo ogni istruzione se c'è un IRQ dal PIC (A)
  • In tal caso, consulta l'IDT per mappare il vettore ricevuto su una funzione
  • Verifica se l'interruzione è stata emessa da una fonte autorizzata
  • Salva i registri del processo interrotto
  • Chiamare la funzione corrispondente per gestire l'interrupt
  • Carica i registri salvati di recente del processo interrotto e prova a riprenderlo
22
wag

Innanzitutto i partecipanti alla gestione degli interrupt sono dispositivi hardware periferici, controller di interrupt, CPU, kernel del sistema operativo e driver. I dispositivi hardware periferici sono responsabili della generazione di interruzioni. Asseriscono le linee di richiesta di interruzione quando desiderano l'attenzione del kernel del sistema operativo. Questi segnali sono multiplexati dal controller di interrupt, che è responsabile della raccolta dei segnali di interrupt. È inoltre responsabile della determinazione dell'ordine in cui i segnali di interruzione verranno passati alla CPU. Il controller di interruzione è in grado di disabilitare temporaneamente una particolare riga di richiesta di interruzione (IRQL) e riattivarla nuovamente (mascheramento IRQL). Il controller di interruzione passa sequenzialmente le richieste di interruzione raccolte alla CPU. CPU dopo il completamento dell'esecuzione di ciascuna istruzione La CPU verifica se vi sono richieste di interrupt in attesa dal controller di interrupt. Se la CPU rileva che è presente una richiesta di attesa E il flag Abilita interruzione è impostato nel registro di controllo interno della CPU, la CPU avvia la gestione degli interrupt. Come puoi vedere, manipolando il flag di interrupt nella CPU e comunicando con il controller di interrupt, il kernel Linux è in grado di controllare l'accettazione degli interrupt. Ad esempio, Linux può disabilitare l'accettazione degli interrupt dal particolare dispositivo o disabilitare affatto l'accettazione degli interrupt.

Cosa succede quando il processore riceve una richiesta di interruzione? Innanzitutto, la CPU disabilita automaticamente gli interrupt ripristinando il Flag di interrupt. Saranno riattivati ​​al termine della gestione degli interrupt. Allo stesso tempo, la CPU compie una quantità minima di lavoro necessario per passare dalla modalità utente alla modalità kernel in modo tale da consentirle di riprendere l'esecuzione del codice interrotto. La CPU consulta le speciali strutture di controllo della CPU riempite dal kernel Linux per trovare un indirizzo di codice al quale verrà passato il controllo. Questo indirizzo è l'indirizzo della prima istruzione del gestore di interrupt, che fa parte del kernel Linux.

Come primo passo della gestione degli interrupt il kernel identifica il vettore di interrupt ricevuto per identificare quale tipo di evento è accaduto nel sistema. Il vettore di interruzione definisce quali azioni prenderà Linux per gestirlo. Come secondo passo Linux salva il resto dei registri della CPU (che non sono stati salvati automaticamente dalla CPU) e che potenzialmente possono essere utilizzati dal programma interrotto. Questa è un'azione molto importante, perché consente a Linux di gestire gli interrupt in modo trasparente rispetto al programma interrotto. Come terzo passo, Linux compie il passaggio alla modalità kernel impostando l'ambiente kernel e impostando lo stato della CPU richiesto. Infine, viene chiamato il gestore di interrupt dipendente dal vettore. (Puoi guardare la macro BUILD_INTERRUPT3 in Arch\x86\kernel\entry_32.S per prendere i dettagli aggiuntivi per un esempio relativo all'architettura x86) Nel caso dei dispositivi periferici questa è una routine do_IRQ (). (Guarda in Arch\x86\kernel\irq.c)

Il gestore di interrupt dipendente dal vettore di solito è avvolto dalle chiamate a irq_enter () e irq_exit (). L'area di codice racchiusa in una coppia di queste funzioni, è atomica rispetto a qualsiasi altra di tali aree ed è anche atomica rispetto a coppie di cli/sti. Anche Irq_enter () e irq_exit () acquisiscono alcune statistiche relative alla gestione degli interrupt. Infine, il kernel esamina la tabella vector_irq per trovare il numero irq assegnato al vettore dell'interrupt ricevuto e chiama handle_irq () (da Arch\x86\kernel\irq_32.c).

A questo punto termina la parte comune della gestione degli interrupt in Linux, poiché il kernel osserva la routine del gestore di interrupt dipendente dal dispositivo installata dal driver del dispositivo come parte del descrittore irq e lo richiama. Se tale gestore non è stato installato dal driver, il kernel riconosce semplicemente l'interrupt sul controller di interrupt e esce dall'handler di interrupt generale.

Dopo la fine dell'interrupt il kernel di gestione ripristina lo stato del programma che era stato precedentemente interrotto e riprende l'esecuzione del programma.

8
ZarathustrA

Dall'aspetto teorico, quasi tutto è stato spiegato. Ma se stai cercando una spiegazione sul framework del codice di gestione degli interrupt del kernel, dovresti seguire il seguente link: na passeggiata di codice all'interno della gestione degli interrupt del kernel

E se stai ancora guardando la teoria sugli interruttori e i gestori di interrupt, allora ti consiglio di leggere questo: Comprensione degli interruttori e dei gestori di interrupt

3
trukna