2010-03-20 15 views
19

Come posso implementare la gestione dei segnali per Ctrl-C e Ctrl-D in C .... Quindi, se Ctrl-C viene premuto, il programma ignorerà e cercherà di ottenere di nuovo l'input dall'utente. ..se si preme Ctrl-D, allora il programma terminerà ...Gestione dei segnali in C

il mio programma segue:

int main(){ 
char msg[400]; 

while(1){ 
    printf("Enter: "); 
    fgets(msg,400,stdin); 
    printf("%s\n",msg); 
} 
} 

Grazie,

Dave

+3

io non consiglierei questo. Ci sono pochissime istanze in cui posso pensare a dove sia una buona idea per un programma scavalcare la funzione kill di Ctrl-C - uno strumento di connessione remota come SSH che è uno di questi. –

+0

Questo è solo per capire come gestire i segnali – Dave

+1

Qualsiasi tipo di programma interprete dovrebbe catturare ctrl-C per interrompere il programma ospitato, se è in esecuzione. – Potatoswatter

risposta

2

Nel tuo esempio sembra che si don' Ho bisogno di CTRL-C handli e per niente. Un "segnale (SIGINT, SIG_IGN)" sembra sufficiente per te, a meno che la tua applicazione non debba gestire un SIGINT proveniente da un'altra fonte. CTRL-D di solito non genera segnali, comunica semplicemente la condizione EOF. È possibile controllare in generale il comportamento del terminale (stiamo parlando dell'input della console, non lo è?) Utilizzando lo termios library (anche here). È possibile attivare, ridefinire o disattivare il carattere "interrupt" (CTRL-C), il EOF uno e molti altri quelli (XON, XOFF, controllo modem ...)

saluti

13

Innanzitutto, Ctrl + D è un indicatore EOF che non puoi intercettare, quando un programma è in attesa di input, premendo Ctrl + D significa fine del file e non aspettarti più input. D'altra parte, utilizzando Ctrl + C per terminare un programma - che è SIGINT, che può essere intrappolato in questo modo:

#include <stdio.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <stdarg.h> 

static void signal_handler(int); 
static void cleanup(void); 
void init_signals(void); 
void panic(const char *, ...); 

struct sigaction sigact; 
char *progname; 

int main(int argc, char **argv){ 
    char *s; 
    progname = *(argv); 
    atexit(cleanup); 
    init_signals(); 
    // do the work 
    exit(0); 
} 

void init_signals(void){ 
    sigact.sa_handler = signal_handler; 
    sigemptyset(&sigact.sa_mask); 
    sigact.sa_flags = 0; 
    sigaction(SIGINT, &sigact, (struct sigaction *)NULL); 
} 

static void signal_handler(int sig){ 
    if (sig == SIGINT) panic("Caught signal for Ctrl+C\n"); 
} 

void panic(const char *fmt, ...){ 
    char buf[50]; 
    va_list argptr; 
    va_start(argptr, fmt); 
    vsprintf(buf, fmt, argptr); 
    va_end(argptr); 
    fprintf(stderr, buf); 
    exit(-1); 
} 

void cleanup(void){ 
    sigemptyset(&sigact.sa_mask); 
    /* Do any cleaning up chores here */ 
} 
+0

Il gestore SIG_IGN si adatta perfettamente alle esigenze dell'OP. – outis

+2

Perché sigact è una variabile globale? Perché la pulizia gioca con essa; dovresti chiamare nuovamente sigaction() perché le modifiche a sigact influenzino il modo in cui il programma si comporta. –

+0

@JonathanLeffler: Potresti spiegarmi meglio perché non è una buona idea dichiarare sigact global, per favore? Mi piacerebbe capire questo punto. Grazie. – Kyrol

31

Quando si tratta di segnali POSIX, si dispone di due mezzi a vostra disposizione. In primo luogo, il modo facile (ma deprecato), signal(). In secondo luogo, il modo più elegante, attuale ma complesso, sigaction(). Si prega di utilizzare sigaction() a meno che non si scopre che non è disponibile su alcune piattaforme su cui è necessario lavorare.

This chapter del manuale di glibc spiega le differenze tra i due e fornisce un buon esempio di codice su come utilizzare entrambi. Elenca anche i segnali che possono essere gestiti, raccomanda come devono essere gestiti e spiega come ogni dato segnale è (o non è) attualmente gestito. È molto più codice di quello che vorrei incollare in una risposta qui, quindi i collegamenti.

Vale davvero la pena l'ora o due che ti porterebbe a leggere i collegamenti e lavorare attraverso gli esempi. La gestione del segnale (specialmente nei programmi che demonizzano) è estremamente importante. Un buon programma dovrebbe gestire tutti i segnali fatali che possono essere gestiti (cioè SIGHUP) ed ignorare esplicitamente i segnali che potrebbero non essere utilizzati (ad esempio SIGUSR1/SIGUSR2).

Inoltre non farà male a studiare la differenza tra i segnali normali e in tempo reale, almeno fino alla comprensione di come il kernel fonde il precedente e non il secondo.

Una volta analizzato, probabilmente ti sentirai incline a scrivere un set di funzioni facile da modificare per gestire i segnali e riutilizzare quel codice più e più volte.

Ci scusiamo per non aver dato un frammento di codice rapido e sporco per mostrare come risolvere il bisogno immediato, ma questo non è un argomento rapido e sporco :)

2

Questo è un programma per la gestione di segnale quando viene premuto Ctrl + c

La sintassi per la funzione del segnale è: signal(signal name, function name);

#include<stdio.h> 
#include<signal.h> // for handling signal 

void signal_handler() 
{ 
    printf("Signal Handled here\n"); 
} 

main() 
{ 
    printf("In main function..\n"); 

    // SIGINT is signal name create when Ctrl+c will pressed 
    signal(SIGINT,signal_handler); 

    sleep(15); 

    printf("In main after called from signal_handle \n"); 

} 
+0

'signal()' è deprecato e dovrebbe essere evitato laddove possibile, quasi tutte le piattaforme moderne (ad eccezione di alcuni incorporati) offrono 'sigaction()'. –

0
#include<signal.h> 
#include<unistd.h> 
#include<stdio.h> 
void signal_catch() 
{ 
    printf("hi,Your signal catched Here"); 
} 
int main() 
{ 
    signal(SIGINT,signal_catch); 
//press ctrl+c 
    sleep(10); 
    return 0; 
}//end main 

//if you want to simply ignore ctrl+c interrupt use following code in main 

int main() 
{ 
    signal(SIGINT,SIG_IGN); 
    sleep(100); 
    return 0; 
}//end main 
//this program wont accept ctrl+c interrupt for 100 seconds. 
Problemi correlati