2009-11-23 26 views
24
#include <stdio.h> 
#include <signal.h> 


void ALARMhandler(int sig) 
{ 
    signal(SIGALRM, SIG_IGN);   /* ignore this signal  */ 
    printf("Hello"); 
    signal(SIGALRM, ALARMhandler);  /* reinstall the handler */ 
} 

int main(int argc, char *argv[]) 
{ 
    alarm(2);      /* set alarm clock   */ 
    while (1) 
    ; 
    printf("All done"); 
} 

que esperan que el programa para imprimir "hola" después de 2 segundos, pero en lugar de la salida es "zsh: alarma ./a.out"señales simples - la programación y la alarma de función C

Cualquier idea de lo que es pasando?

Respuesta

31

Olvidó establecer inicialmente el controlador de alarma. Cambiar el inicio de main() gustan:

int main(int argc, char *argv[]) 
{ 
    signal(SIGALRM, ALARMhandler); 
    ... 

Además, el manejador de señales probablemente imprimir nada. Eso es porque la biblioteca C almacena en caché hasta que ve un final de línea. Entonces:

void ALARMhandler(int sig) 
{ 
    signal(SIGALRM, SIG_IGN);   /* ignore this signal  */ 
    printf("Hello\n"); 
    signal(SIGALRM, ALARMhandler);  /* reinstall the handler */ 
} 

Para un programa del mundo real, la impresión desde un manejador de señal no es muy segura. Un manejador de señal debe hacer tan poco como pueda, preferiblemente solo colocando una bandera aquí o allá. Y la bandera debe declararse volatile.

+22

Real- ejemplo mundial: una vez trabajé en un sistema que usaba una base de datos de Access como back-end, y bajo ciertas circunstancias una llamada 'printf()' en un manejador de señal escribía en el archivo .mdb en lugar de stdout, manchando la base de datos irreparablemente . –

5

No está instalando primero el controlador de señal.
Necesita decirle al sistema que desea manejar la señal antes de recibirla, por lo que debe llamar al signal() desde la línea principal antes de que llegue la señal.

int main(int argc, char *argv[]) 
{ 
    signal(SIGALRM, ALARMhandler);  /* install the handler */ 
    alarm(2);      /* set alarm clock   */ 
    while (1); 
} 
9

No está configurando el controlador en su función main.

Antes de hacer alarm(2), ponga signal(SIGALRM, ALARMhandler); en su main.

Debería funcionar entonces.

Tenga en cuenta que su "Todo listo" nunca se imprimirá, porque permanecerá en el ciclo while (1) después de que se haya ejecutado el procesador de señal. Si desea que el bucle se rompa, deberá tener un indicador que cambie el manejador de señal.

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

/* number of times the handle will run: */ 
volatile int breakflag = 3; 

void handle(int sig) { 
    printf("Hello\n"); 
    --breakflag; 
    alarm(1); 
} 

int main() { 
    signal(SIGALRM, handle); 
    alarm(1); 
    while(breakflag) { sleep(1); } 
    printf("done\n"); 
    return 0; 
} 
+4

+1 Para el buen programa. Creo que tendrías que llamar 'alarm (2)' en el manejador de señal: normalmente una llamada 'alarm()' solo genera un solo 'SIGALRM' – Andomar

+0

Por supuesto, tienes razón. Obviamente no probé este código, y no he usado señales de esta manera por un tiempo (notablemente, son inútiles en un entorno de subprocesos para usar de esta manera). – McPherrinM

+0

¿Cuál es la necesidad de dar clase de almacenamiento volátil para la variable breakflag? – sujin

4

Andomar is rigth. Puedo probar esto y, versión 1 impresiones (cada segundo):

Hi... 
Hi... 
Hi... 
Hi... 
BYE 
Hi... 
... 

versión 2 impresiones (cada cinco segundos):

Hi...Hi...Hi...Hi...BYE 
Hi...Hi...Hi...Hi...BYE 
... 

Así que el código es:

#include <stdio.h> 
#include <unistd.h> 
#include <signal.h> 

# define T 5 

int flag = T; 

void sigalrm_handler(int); 

int main(void) 
{ 
    signal(SIGALRM, sigalrm_handler); 
    alarm(1);       
    while (1); 
} 

void sigalrm_handler(int sig) 
{ 
    if(--flag){ 
     printf("Hi...\n"); /*version 1*/ 
     /*printf("Hi...");*/ /*version 2*/ 
    }else{ 
     printf("BYE\n"); 
     flag=T;  
    } 
    alarm(1); 
} 
+0

Gracias por un código completo y funcional. Acabo de pegarlo en la parte superior del {} principal de mi programa existente y lo encendí. – user2548100

Cuestiones relacionadas