4.3. Interrupt e Ottimizzazione IRQ
Un interrupt request (IRQ) è una richiesta per il servizio inviata a livello hardware. Gli interrupt possono essere inviati da un hardware specifico o attraverso un bus hardware come pacchetto di informazioni (un Message Signaled Interrupt, o MSI).
In presenza di interrupt, alla ricezione di un IRQ si verificherà uno smistamento ad un stato interrupt. Il codice di smistamento degli interrupt del kernel recupera il valore IRQ insieme all'elenco associato di Interrupt Service Routines (ISR) registrati, invocando a turno ogni ISR. ISR riconoscerà il segnale e ignorerà gli interrupt ridondanti dello stesso IRQ, mettendo in coda un gestore per la processazione dell'interrupt impedendo ad ISR di ignorare gli interrupt futuri.
Il file
/proc/interrupts
elenca il numero di interrupt per CPU per dispositivo I/O. Mostra il numero di IRQ, il numero dell'interrupt gestito da ogni CPU core, il tipo di interrupt ed un elenco delimitato da virgole di driver registrati per ricevere il segnale. (Consultare la pagina man proc(5) per maggiori informazioni: man 5 proc
)
Gli IRQ presentano una proprietà "affinity" associata,
smp_affinity
, la quale definisce i CPU core in grado di eseguire ISR per l'IRQ in questione. Usare questa proprietà per migliorare le prestazioni dell'applicazione assegnando sia l'affinità dell'interruzione che quella del thread dell'applicazione ad uno più CPU core. Ciò permette di avere una linea di condivisione della cache tra l'interrupt specificato ed i thread dell'applicazione.
Il valore dell'affinità dell'interrupt per un particolare numero IRQ è archiviato nel file
/proc/irq/IRQ_NUMBER/smp_affinity
associato, disponibile e modificabile dall'utente root. Il valore archiviato in questo file è una maschera di bit esadecimale che rappresenta tutti i CPU core presenti nel sistema.
Per esempio, per impostare l'affinità dell'interrupt per il driver Ethernet su un server con quattro CPU core, determinare prima il numero IRQ associato con il driver Ethernet:
# grep eth0 /proc/interrupts 32: 0 140 45 850264 PCI-MSI-edge eth0
Utilizzare il valore IRQ per rilevare il file
smp_affinity
appropriato:
# cat /proc/irq/32/smp_affinity f
Il valore predefinito per smp_affinity è
f
, ciò significa che IRQ può essere servito su qualsiasi CPU del sistema. L'impostazione di questo valore su 1
indicherà che solo la CPU 0 può servire questo interrupt:
# echo 1 >/proc/irq/32/smp_affinity # cat /proc/irq/32/smp_affinity 1
Usare le virgole per delimitare i valori di
smp_affinity
per gruppi a 32-bit discreti. Questa impostazione è necessaria per sistemi con un numero di core maggiore di 32. Di seguito viene riportato un esempio nel quale IRQ 40 viene servito su tutti i core di un sistema a 64-core:
# cat /proc/irq/40/smp_affinity ffffffff,ffffffff
Per servire IRQ 40 solo nella parte alta di un 32-core in un sistema a 64-core, eseguire quanto di seguito riportato:
# echo 0xffffffff,00000000 > /proc/irq/40/smp_affinity # cat /proc/irq/40/smp_affinity ffffffff,00000000
Nota
Su sistemi che supportano gli interrupt steering, se modificate
smp_affinity
di un IRQ, la decisione di servire un interrupt con una CPU particolare viene presa a livello hardware senza alcun intervento da parte del kernel.