Sto sviluppando un'applicazione che utilizza C++ e compila usando il compilatore GNU C di Linux. Tuttavia, voglio invocare una funzione in quanto l'utente interrompe lo script utilizzando CtrlC chiavi. Cosa dovrei fare? Qualsiasi risposta sarebbe molto apprezzata.Gestione degli eventi di interrupt Ctrl + C in Linux
risposta
Quando si preme Ctr + C, il sistema operativo invia un signal al processo . Ci sono molti segnali e uno di loro è SIGINT. SIGINT ("interrupt di programma") è uno dei segnali di terminazione.
Ci sono alcuni altri tipi di segnali di terminazione, ma la cosa interessante di SIGINT è che può essere gestito (catturato) dal programma. L'azione predefinita di SIGINT è la chiusura del programma. Cioè, se il tuo programma non gestisce specificamente questo segnale, quando si preme Ctr + C il programma termina come azione predefinita.
Per modificare l'azione predefinita di un segnale, è necessario registrare il segnale da rilevare. Per registrare un segnale in un programma C (almeno con 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 della funzione signal
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: si dovrebbe chiamare solo safe/authorized functions nel gestore di segnale. Ad esempio avoid calling printf in signal handler.
È possibile compilare questo codice con gcc ed eseguirlo dalla shell. C'è un ciclo infinito nel codice e verrà eseguito finché non si invierà un segnale SIGINT
premendo Ctr + C.
Puoi lasciare commenti per i tuoi dubbi, cerco solo di darti un rapido punto di partenza. Credo che con ulteriori sforzi esplorerai le cose in dettaglio. –
Grazie per le risposte gentili e la risposta, che funziona alla grande. – mozcelikors
Sono abbastanza sicuro che al processo venga inviato un segnale, non un singolo. :-) – celtschk
Digitando CtrlC provoca normalmente il guscio di inviare SIGINT
al vostro programma. Aggiungi un gestore per quel segnale (tramite signal(2)
o sigaction(2)
) e puoi fare ciò che ti piace quando CtrlC viene premuto.
In alternativa, se si desidera solo eseguire la pulizia prima che il programma venga chiuso, la configurazione di un gestore di uscita tramite atexit(3)
potrebbe essere più appropriata.
È possibile utilizzare la macro del segnale.
Ecco un esempio di come trattare con esso: uscita
#include <signal.h>
#include <stdio.h>
void sigint(int a)
{
printf("^C caught\n");
}
int main()
{
signal(SIGINT, sigint);
for (;;) {}
}
Esempio:
Ethans-MacBook-Pro:~ phyrrus9$ ./a.out
^C^C caught
^C^C caught
^C^C caught
^C^C caught
^C^C caught
evitare di utilizzare printf nel gestore di segnale –
Semplice come quello. Lo uso per chiudere la connessione i2c in modo che la funzione printf venga sostituita con funzioni di killing della connessione. Grazie davvero. – mozcelikors
È necessario [Definire Signal Handlers] (http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_21.html#SEC351) per SIGINT, avere un'idea da [questo code] (http: // StackOverflow.it/questions/17705842/is-there-a-way-to-make-my-program-work-with-less-code) –
Come ha a che fare questo con il compilatore usato? –
@mozcelikors Non esistono "biblioteche riconosciute dal GCC". Se c'è una libreria scritta in C standard, qualsiasi compilatore C sane dovrebbe essere in grado di compilarlo. –