• Viernes 8 de Noviembre de 2024, 23:21

Autor Tema:  Señales y temporizadores en C  (Leído 1532 veces)

guiu

  • Nuevo Miembro
  • *
  • Mensajes: 3
    • Ver Perfil
Señales y temporizadores en C
« en: Lunes 15 de Junio de 2009, 11:00 »
0
Hola a todos,

Soy nuevo en el foro, y medianamente novato en esto de la programación en C, sobre todo a cierto nivel. Estoy haciendo un cliente TCP que pide datos a un servidor de manera asíncrona. Quiero que este programa, cada x tiempo (es decir, de manera síncrona), vigile si otro está vivo (digamos que cuida de su hermano). Para el envío y recepción de datos uso sockets, y en la rx en concreto utilizo la función select() sobre sockets bloqueantes). Para realizar la vigilancia del proceso hermano, hago uso del temporizador del sistema mediante la función setitimer. El modo que tengo de hacer esta vigilancia es leer de un fichero un el valor que escribe el programa hermano, y ver que, efectivamente, este valor va cambiando. Cuando está un rato sin cambiar considero que el hermano ha muerto (d.e.p.).

Para hacer el acceso al fichero "que vigilo", en la función que maneja SIGALRM hago un fork, de modo que se cree una hebra específica para hacer esa tarea (digamos que no solo tengo que relanzar el proceso hermano cuando veo que se ha caído, sino que tengo que hacer unas cuantas cosas más, por eso hago el fork()). Tengo varios problemas:

- En primer lugar, pese a lazar el setitimer en su versión REAL_TIME, veo que el tiempo entre señales SIGALRM no se ajusta "demasiado" a lo que le pido. Pongamos que le pido 25 segundo de timer. El salto de la señal se produce, variando cada vez, en torno a los 40 segundo o así. Y cada vez parece que tarda más. He de decir que lo que hago es, en una función de definición de señales, determino los signal_handler de las señales que me interesen, para, al final de esta función, iniciar el temporizador (sin valor de reactivación, sólo tocando el it_value) Depués, al final del signal_handler de SIGALRM vuelvo a lanzar el timer.
- Para hacer la asignación de los manejadores, he usado tanto signal como sigset para no tener que "recargar" el manejador. En ambos casos, veo que tras cierto número de señales capturadas correctamente, parece que deja de hacerlo (o no se reinicia el timer o no se captura la SIGALRM, pero dejan de hacerse accesos al fichero de vigilancia)

Os adjunto el código del definición de señales y el manejador de la señal de alarma, por si véis algo raro.



<code>
void signal_definitions(){
    int i;
    int error;
    //memset(&sigTimerAction, 0, sizeof(sigTimerAction));
   
    printf("Estoy en la definicion de señalesn");
    for (i=1;i<NSIG;i++) {
        if ((i==SIGKILL) || (i==SIGSTOP) || (i==SIGCHLD)) continue;
        if ((i==SIGHUP) || (i==SIGINT) || (i==SIGQUIT) ||
            (i==SIGTSTP) || (i==SIGCONT) || (i==SIGTTIN) ||
            (i==SIGTTOU)) {
                signal(i,SIG_IGN);
                continue;
        }
       
        if (i==SIGALRM){
            if (sigset(i,watchdogCheck) == SIG_ERR){
            //if (signal(i,watchdogCheck) == SIG_ERR){
                sprintf(msg_log, "Error al manejar señal SIGALARMn");
                logError();
                exit(-1);
            }
            continue;
        }

        if (signal(i,process_exit) == SIG_ERR) {
            sprintf(msg_log, "Error al manejar señal de salida del programan");
            logError();
            exit(-1);
        }

    }

   
    // Defino parametros de tiempo para temporizador
    setvalortimer.it_interval.tv_sec = 0;
    setvalortimer.it_interval.tv_usec = 0;
    setvalortimer.it_value.tv_sec = 25;
    setvalortimer.it_value.tv_usec = 0;
       
    // Defino valores iniciales para variables de lectura y escritura del watchdog
    num_escrito = 0;
    num_leido = 0;
   
    // Lanzo timer
    setitimer(ITIMER_REAL,&setvalortimer,&ovalortimer);
    //error = setitimer(ITIMER_VIRTUAL,&setvalortimer,&ovalortimer);
    printf("Definicion: %dn",error);
   
    //alarm(20);
   
}
void watchdogCheck(int signum){
 
    int error;
    int pid;
   
    //signal(SIGALRM,watchdogCheck);
    printf("Estoy en wdCheck antes del waitn");
   
    wait(); //Soy el padre y espero a que acabe el hijo que lancé.
    printf("Estoy en wdCheck despues del waitn");
    pid = fork();
   
    if (pid < 0){
        sprintf(msg_log, "Watchdog: imposible crear hebra de vigilancia %d",nArmario);
        logError();
    }
       
    else if (pid == 0){
        printf("Soy el proceso hijon");
        error = wd_escritura();
        if (error < 0){
            sprintf(msg_log, "Watchdog: no puede hacerse vigilancia sobre el armario %d",nArmario);
            logError();
            //exit(-1);
        }
        error = wd_lectura();
        if (error < 0){
            sprintf(msg_log, "Watchdog: no puede hacerse vigilancia sobre el armario %d",nArmario_otro);
            logError();
            //exit(-1);
        }
        exit(0);
    }
    else {
   
   
   
    //sigemptyset( &sigTimerAction.sa_mask );
    //sigTimerAction.sa_flags = 0;
    //sigTimerAction.sa_handler = watchdogCheck;
    //sigaction(SIGALRM, &sigTimerAction, NULL);
    //signal(SIGALRM,watchdogCheck);
//if (signal(SIGALRM,watchdogCheck)==SIG_ERR)
    //    printf("Error en redefinicionn");
    setvalortimer.it_interval.tv_sec = 0;
    setvalortimer.it_interval.tv_usec = 0;
    setvalortimer.it_value.tv_sec = 15;
    setvalortimer.it_value.tv_usec = 0;
    error = setitimer(ITIMER_REAL,&setvalortimer,&ovalortimer);
    printf("WdCheck: %dn",error);
    //setitimer(ITIMER_VIRTUAL,&setvalortimer,&ovalortimer);
    //alarm(10);
    }
}
</code>


Bueno, bonito chorizo el que acabo de escribir. Si alguien puede echarme una mano le estaré enormemente agradecido. Ya os digo que no controlo demasiado este tema; lo que sé lo sé por haber leído por la red en sitios como éste.

Muchas gracias de antemano.

m0skit0

  • Miembro de PLATA
  • *****
  • Mensajes: 2337
  • Nacionalidad: ma
    • Ver Perfil
    • http://fr33kk0mpu73r.blogspot.com/
Re: Señales y temporizadores en C
« Respuesta #1 en: Lunes 15 de Junio de 2009, 13:27 »
0
Cita de: "guiu"
Bueno, bonito chorizo el que acabo de escribir
Feo  :lol: Usa las etiquetas de código y ponlo formateado :P

guiu

  • Nuevo Miembro
  • *
  • Mensajes: 3
    • Ver Perfil
Re: Señales y temporizadores en C
« Respuesta #2 en: Lunes 15 de Junio de 2009, 14:01 »
0
Uos, ok, ahí va el código:
Código: C
  1.  
  2. void signal_definitions(){
  3. int i;
  4. int error;
  5. //memset(&sigTimerAction, 0, sizeof(sigTimerAction));
  6.  
  7. printf("Estoy en la definicion de señalesn");
  8. for (i=1;i<NSIG;i++) {
  9. if ((i==SIGKILL) || (i==SIGSTOP) || (i==SIGCHLD)) continue;
  10. if ((i==SIGHUP) || (i==SIGINT) || (i==SIGQUIT) ||
  11. (i==SIGTSTP) || (i==SIGCONT) || (i==SIGTTIN) ||
  12. (i==SIGTTOU)) {
  13. signal(i,SIG_IGN);
  14. continue;
  15. }
  16.  
  17. if (i==SIGALRM){
  18. if (sigset(i,watchdogCheck) == SIG_ERR){
  19. //if (signal(i,watchdogCheck) == SIG_ERR){
  20. sprintf(msg_log, "Error al manejar señal SIGALARMn");
  21. logError();
  22. exit(-1);
  23. }
  24. continue;
  25. }
  26.  
  27. if (signal(i,process_exit) == SIG_ERR) {
  28. sprintf(msg_log, "Error al manejar señal de salida del programan");
  29. logError();
  30. exit(-1);
  31. }
  32.  
  33. }
  34.  
  35.  
  36. // Defino parametros de tiempo para temporizador
  37. setvalortimer.it_interval.tv_sec = 0;
  38. setvalortimer.it_interval.tv_usec = 0;
  39. setvalortimer.it_value.tv_sec = 25;
  40. setvalortimer.it_value.tv_usec = 0;
  41.  
  42. // Defino valores iniciales para variables de lectura y escritura del watchdog
  43. num_escrito = 0;
  44. num_leido = 0;
  45.  
  46. // Lanzo timer
  47. setitimer(ITIMER_REAL,&setvalortimer,&ovalortimer) ;
  48. //error = setitimer(ITIMER_VIRTUAL,&setvalortimer,&ovalortim er);
  49. printf("Definicion: %dn",error);
  50.  
  51. //alarm(20);
  52.  
  53. }
  54. void watchdogCheck(int signum){
  55.  
  56. int error;
  57. int pid;
  58.  
  59. //signal(SIGALRM,watchdogCheck);
  60. printf("Estoy en wdCheck antes del waitn");
  61.  
  62. wait(); //Soy el padre y espero a que acabe el hijo que lancé.
  63. printf("Estoy en wdCheck despues del waitn");
  64. pid = fork();
  65.  
  66. if (pid < 0){
  67. sprintf(msg_log, "Watchdog: imposible crear hebra de vigilancia %d",nArmario);
  68. logError();
  69. }
  70.  
  71. else if (pid == 0){
  72. printf("Soy el proceso hijon");
  73. error = wd_escritura();
  74. if (error < 0){
  75. sprintf(msg_log, "Watchdog: no puede hacerse vigilancia sobre el armario %d",nArmario);
  76. logError();
  77. //exit(-1);
  78. }
  79. error = wd_lectura();
  80. if (error < 0){
  81. sprintf(msg_log, "Watchdog: no puede hacerse vigilancia sobre el armario %d",nArmario_otro);
  82. logError();
  83. //exit(-1);
  84. }
  85. exit(0);
  86. }
  87. else {
  88.  
  89.  
  90.  
  91. //sigemptyset( &sigTimerAction.sa_mask );
  92. //sigTimerAction.sa_flags = 0;
  93. //sigTimerAction.sa_handler = watchdogCheck;
  94. //sigaction(SIGALRM, &sigTimerAction, NULL);
  95. //signal(SIGALRM,watchdogCheck);
  96. //if (signal(SIGALRM,watchdogCheck)==SIG_ERR)
  97. // printf("Error en redefinicionn");
  98. setvalortimer.it_interval.tv_sec = 0;
  99. setvalortimer.it_interval.tv_usec = 0;
  100. setvalortimer.it_value.tv_sec = 15;
  101. setvalortimer.it_value.tv_usec = 0;
  102. error = setitimer(ITIMER_REAL,&setvalortimer,&ovalortimer) ;
  103. printf("WdCheck: %dn",error);
  104. //setitimer(ITIMER_VIRTUAL,&setvalortimer,&ovalortim er);
  105. //alarm(10);
  106. }
  107. }
  108.  
  109.  
  110.  

Gracias de nuevo