2010-03-20 38 views
19

¿Cómo puedo implementar Manejo de señales para Ctrl-C y Ctrl-D en C ...? Entonces, si se presiona Ctrl-C, el programa ignorará e intentará obtener la información del usuario nuevamente. ..si se pulsa Ctrl-D, entonces el programa terminará ...Manejo de señales en C

Mi programa sigue:

int main(){ 
char msg[400]; 

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

Gracias,

de Dave

+3

no recomendaría esto. Hay muy pocas instancias en las que puedo pensar que es una buena idea que un programa anule la función de cierre de Ctrl-C, una herramienta de conexión remota como SSH es una de ellas. –

+0

Esto es solo para comprender cómo manejar Señales – Dave

+1

Cualquier tipo de programa de intérprete debe capturar ctrl-C para abortar el programa alojado, si se está ejecutando. – Potatoswatter

Respuesta

2

En su ejemplo parece usted don' Necesito CliT-C handli nd en absoluto. Una "señal (SIGINT, SIG_IGN)" parece suficiente para usted, a menos que su aplicación deba manejar un SIGINT proveniente de alguna otra fuente. CTRL-D generalmente no genera señales, simplemente comunica la condición EOF. En general, puede controlar el comportamiento de su terminal (estamos hablando de la entrada de la consola, ¿no?) Utilizando el termios library (también here). Puede activar, desactivar o redefinir el carácter "interrumpir" (Ctrl + C), el EOF uno y muchos otros (XON, XOFF, control del módem ...)

Saludos

13

En primer lugar, Ctrl + D es un indicador EOF que no se puede atrapar, cuando un programa está esperando la entrada, presionar Ctrl + D significa el final del archivo y no esperar más entradas. Por otra parte, usando Ctrl + C para terminar un programa - es decir SIGINT, que puede ser atrapado por hacer esto:

#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

El controlador SIG_IGN se ajustaría muy bien a las necesidades del OP. – outis

+2

¿Por qué se siguect una variable global? ¿Por qué la limpieza juega con eso? tendrías que volver a llamar a sigaction() para que los cambios realizados a sigact afecten la forma en que se comporta el programa. –

+0

@JonathanLeffler: ¿Podrías explicarme mejor por qué no es una buena idea declarar siemprect global, por favor? Me gustaría entender este punto. Gracias. – Kyrol

31

Cuando se trata de señales POSIX, tiene dos medios a su disposición. Primero, el camino fácil (pero obsoleto), signal(). En segundo lugar, la forma más elegante, actual pero compleja, sigaction(). Use sigaction() a menos que descubra que no está disponible en alguna plataforma en la que deba trabajar.

This chapter del manual de glibc explica las diferencias entre los dos y ofrece un buen código de ejemplo sobre cómo usar ambos. También enumera las señales que se pueden manejar, recomienda cómo se manejan y profundiza más sobre cómo saber cómo se maneja (o no) actualmente cada señal dada siendo manejada. Así hay más código del que me gustaría pegar en una respuesta aquí, de ahí los enlaces.

Realmente vale la pena la hora o dos que le tomaría leer los enlaces y trabajar con los ejemplos. El manejo de señales (especialmente en programas que demonizan) es extremadamente importante. Un buen programa debe manejar todas las señales fatales que se pueden manejar (es decir, SIGHUP) e ignorar explícitamente las señales que podría no estar utilizando (es decir, SIGUSR1/SIGUSR2).

Tampoco está de más estudiar la diferencia entre las señales normales y en tiempo real, al menos hasta la comprensión de cómo el núcleo combina el anterior y no el segundo.

Una vez que lo hagas, probablemente te sientas inclinado a escribir un conjunto de funciones fáciles de modificar para manejar tus señales y volver a usar ese código una y otra vez.

Lo siento por no dar un fragmento de código rápida y sucia para mostrar cómo resolver su necesidad inmediata, pero esto no es un tema rápido y sucio :)

2

Este es un programa para el manejo de la señal cuando se pulsa Ctrl + c

La sintaxis para la función de la señal es: 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()' está en desuso y debe evitarse siempre que sea posible, casi todas las plataformas modernas (salvo algunas incrustadas) ofrecen '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.