Quando premi Ctr + C , il sistema operativo invia un segnale al processo. Ci sono molti segnali e uno di questi è SIGINT. Il SIGINT ("interrupt di programma") è uno dei segnali di terminazione.
Esistono altri tipi di segnali di terminazione, ma la cosa interessante di SIGINT è che può essere gestito (catturato) dal tuo programma. L'azione predefinita di SIGINT è la terminazione del programma. Cioè, se il tuo programma non gestisce specificamente questo segnale, quando premi Ctr + C il tuo programma termina come azione predefinita.
Per modificare l'azione predefinita di un segnale è necessario registrare il segnale da catturare. Per registrare un segnale in un programma C (almeno nei sistemi POSIX) ci sono due funzioni
- signal(int signum, sighandler_t handler);
- sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);.
Queste funzioni richiedono che l'intestazione signal.h sia inclusa nel codice C. Ho fornito un semplice esempio del signal
funzione di seguito con commenti.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h> // our new library
volatile sig_atomic_t flag = 0;
void my_function(int sig){ // can be called asynchronously
flag = 1; // set flag
}
int main(){
// Register signals
signal(SIGINT, my_function);
// ^ ^
// Which-Signal |-- which user defined function registered
while(1)
if(flag){ // my action when signal set it 1
printf("\n Signal caught!\n");
printf("\n default action it not termination!\n");
flag = 0;
}
return 0;
}
Nota:dovresti chiamare solo funzioni sicure/autorizzate nel gestore del segnale. Ad esempio, evita di chiamare printf nel gestore del segnale.
Puoi compilare questo codice con gcc ed eseguirlo dalla shell. C'è un ciclo infinito nel codice e verrà eseguito finché non invii un SIGINT
segnale premendo Ctr + C .
Puoi utilizzare la macro signal.
Ecco un esempio di come gestirlo:
#include <signal.h>
#include <stdio.h>
void sigint(int a)
{
printf("^C caught\n");
}
int main()
{
signal(SIGINT, sigint);
for (;;) {}
}
Esempio di output:
Ethans-MacBook-Pro:~ phyrrus9$ ./a.out
^C^C caught
^C^C caught
^C^C caught
^C^C caught
^C^C caught
Digitando Ctrl C normalmente fa sì che la shell invii SIGINT
al tuo programma. Aggiungi un gestore per quel segnale (tramite signal(2)
o sigaction(2)
), e puoi fare quello che vuoi quando Ctrl C è premuto.
In alternativa, se ti interessa solo eseguire la pulizia prima che il programma esca, imposta un gestore di uscita tramite atexit(3)
potrebbe essere più appropriato.