2013-07-20 3 views
18

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

+0

È 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) –

+8

Come ha a che fare questo con il compilatore usato? –

+3

@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. –

risposta

42

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

  1. signal(int signum, sighandler_t handler);
  2. 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.

+1

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. –

+1

Grazie per le risposte gentili e la risposta, che funziona alla grande. – mozcelikors

+0

Sono abbastanza sicuro che al processo venga inviato un segnale, non un singolo. :-) – celtschk

9

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.

3

È 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 
+7

evitare di utilizzare printf nel gestore di segnale –

+0

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