Foros del Web » Programación para mayores de 30 ;) » C/C++ »

signal: SIGALRM

Estas en el tema de signal: SIGALRM en el foro de C/C++ en Foros del Web. Holas. La pregunta es sencilla, a ver si alguien me lo confirma. Supongamos que quiero hacer un contador un poco especial. Es un contador que ...
  #1 (permalink)  
Antiguo 21/12/2009, 10:43
 
Fecha de Ingreso: abril-2008
Mensajes: 141
Antigüedad: 16 años, 1 mes
Puntos: 0
De acuerdo signal: SIGALRM

Holas.

La pregunta es sencilla, a ver si alguien me lo confirma.

Supongamos que quiero hacer un contador un poco especial. Es un contador que inicialmente vale 0 y que cada vez que se recibe un signal SIGALRM incrementa en 1 el valor y lo pinta por pantalla.

La pregunta es: Es obligatorio tener como variable global el contador o hay alguna otra solucion sin usar variables globales?

Este codigo implementa lo que he dicho pero usando una variable global.

Código C:
Ver original
  1. #include <signal.h>
  2. #include <sys/time.h>
  3. #include <stdio.h>
  4.  
  5. int i = 0;
  6.  
  7. void intSIGALRM (){
  8.         i++;
  9.         printf ("%d\n", i);
  10.         signal (SIGALRM, intSIGALRM);
  11.         alarm (1);
  12. }
  13.  
  14. int main (){
  15.         signal (SIGALRM, intSIGALRM);
  16.         alarm (1);
  17.         while (1);
  18.  
  19.         return 0;
  20. }

Gracias.
  #2 (permalink)  
Antiguo 21/12/2009, 11:37
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Respuesta: signal: SIGALRM

¿TLS? De cualquier manera deberias proteger el recurso (esa variable en este caso) para que se accediera de manera atomica al mismo.
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #3 (permalink)  
Antiguo 22/12/2009, 01:28
 
Fecha de Ingreso: abril-2008
Mensajes: 141
Antigüedad: 16 años, 1 mes
Puntos: 0
Respuesta: signal: SIGALRM

Quizas no te entendi, pero es unicamente una variable global que se usa unicamente en un proceso, es decir, no es memoria compartida por mas procesos y por tanto no hace falta protegerla para que se ejecute en exclusion mutua.

Y sobre lo del thread, pues veo que la cosa se complica demasiado para lo que quiero hacer.

No se puede pasarle parametros a la funcion que se llama con el alarm, no?
  #4 (permalink)  
Antiguo 22/12/2009, 02:23
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Respuesta: signal: SIGALRM

Lo siento, estoy acostumbrado al Kernel y recibir eventos de cualquier hilo de cualquier proceso en cualquier momento, en tu caso el tratamiento de i ocurre cuando el manejador de SIGALRM es el por defecto en un proceso con un solo hilo, entonces no puede haber problemas de sincronizacion.

No, solo podes especificar el numero de señal y su manejador.
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #5 (permalink)  
Antiguo 22/12/2009, 04:57
 
Fecha de Ingreso: abril-2008
Mensajes: 141
Antigüedad: 16 años, 1 mes
Puntos: 0
Respuesta: signal: SIGALRM

Gracias, como siempre dando soluciones :)

Mi aplicacion es un servidor que atiende a clientes. Cada cierto tiempo debe enviar tramas de timeout al cliente y si este no le responde entonces corta la conexion y cierra el socket. Este "cada cierto tiempo" lo implemento con un sigalrm de la misma forma que he hecho el contador anterior.

El problema esta que dentro de la funcion que es llamada por sigalrm no dispongo de la variable socket y, por tanto, no puedo escribir en el. Lo unico que se me ocurre es poner la variable socket (la que se crea con la funcion socket ()) como global, entonces si que podria escribir en el socket.
  #6 (permalink)  
Antiguo 22/12/2009, 05:22
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Respuesta: signal: SIGALRM

¿Sockets bloqueantes en una aplicacion de un solo hilo? ¿Estamos hablando de TCP o UDP? Si es TCP cada cliente tiene un socket ... que devuelve la funcion accept. ¿Como distinguirias a cada cliente en ese caso?

La verdad es que *NIX no es mi campo pero me parece que estas tratando de usar algo que no esta preparado para esto (multiples timers - uno por cada cliente - ejecutandose a la vez):

http://users.evtek.fi/~tk/rtp/signals-programming.html
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #7 (permalink)  
Antiguo 22/12/2009, 05:43
 
Fecha de Ingreso: abril-2008
Mensajes: 141
Antigüedad: 16 años, 1 mes
Puntos: 0
Respuesta: signal: SIGALRM

Cita:
Iniciado por Eternal Idol Ver Mensaje
La verdad es que *NIX no es mi campo pero me parece que estas tratando de usar algo que no esta preparado para esto (multiples timers - uno por cada cliente - ejecutandose a la vez):

http://users.evtek.fi/~tk/rtp/signals-programming.html
Pues si, eso es justo lo que quiero hacer. Una vez el cliente se conecta al servidor , el servidor crea un hijo para atender al cliente. Dentro de este hijo es donde quiero enviar la trama timeout cada cierto tiempo usando el signal alrm.

En procesos diferentes (hijos del server que atienden los clientes) se pueden usar las mismas interrupciones, no?

Voy a probar esto porque ahora me has hecho dudar.
  #8 (permalink)  
Antiguo 22/12/2009, 05:44
Avatar de Eternal Idol  
Fecha de Ingreso: mayo-2004
Ubicación: Lucentum
Mensajes: 6.192
Antigüedad: 20 años
Puntos: 74
Respuesta: signal: SIGALRM

Entonces si, no deberia haber problema si cada proceso del servidor solo tiene un cliente.
__________________
¡Peron cumple, Evita dignifica! VIVA PERON CARAJO
  #9 (permalink)  
Antiguo 22/12/2009, 06:42
 
Fecha de Ingreso: abril-2008
Mensajes: 141
Antigüedad: 16 años, 1 mes
Puntos: 0
De acuerdo Respuesta: signal: SIGALRM

El siguiente codigo es solo un ejemplo para ver que si que se puede usar la misma interrupcion con diferentes procesos, porque al hacer el fork se crea una copia identica (menos el pid), por lo que las variables globales e interrupciones no generan problemas.

No he hecho 2 contadores con un unico SIGALRM porque para ver el resultado por pantalla tendria que modificar ciertas cosas que podrian causar confusion con el objetivo del programa.


Código C:
Ver original
  1. #include <signal.h>
  2. #include <stdio.h>
  3.  
  4. int n = 0;
  5.  
  6. void intSIGUSR1 (){
  7.         printf ("%d\n", n);
  8. }
  9.  
  10. int main (){
  11.         int pidHijo1, pidHijo2;
  12.  
  13.         pidHijo1 = fork ();
  14.  
  15.         if (pidHijo1 == 0){
  16.                 //Hijo
  17.                 signal (SIGUSR1, intSIGUSR1);
  18.                 n = 1;
  19.                 kill (getpid (), SIGUSR1);
  20.  
  21.                 exit (0);
  22.         }else if (pidHijo1 < 0){
  23.                 //Error
  24.                 exit (-1);
  25.         }
  26.  
  27.         pidHijo2 = fork ();
  28.  
  29.         if (pidHijo2 == 0){
  30.                 //Hijo
  31.                 signal (SIGUSR1, intSIGUSR1);
  32.                 n = 2;
  33.                 kill (getpid (), SIGUSR1);
  34.  
  35.                 exit (0);
  36.         }else if (pidHijo2 > 0){
  37.                 //Padre
  38.                 waitpid (pidHijo1, NULL, 0);
  39.                 waitpid (pidHijo2, NULL, 0);
  40.         }else{
  41.                 //Error
  42.                 exit (-1);
  43.         }
  44.  
  45.         return 0;
  46. }

Este programa solo muestra 1 y 2 por pantalla, o 2 y 1, si el scheduler asi lo decide.

En lugar de la variable global n, ahi pondria la variable del socket.

Primero haria el accept (). Una vez llega un cliente esta funcion me devuelve el fd del socket. Este fd lo copio en la variable global y genero un hijo para atender al cliente. Listo, el hijo tendra el fd del socket en la variable global con el que se comunicara con el cliente y a la vez se podra usar para enviar timeouts.

Si llegan mas conexiones de clientes pues no pasa nada. De la misma forma se guarda en la variable global el fd del socket creado con accept () y se crea el hijo, el cual tendra en esta variable global el fd del socket con el que se comunicara con el cliente.

Puede que al principio se piense que se esta usando memoria compartida (la variable global) entre proceso padre e hijo, pero no es asi. El siguiente codigo lo deja mas claro:

Código C:
Ver original
  1. #include <stdio.h>
  2.  
  3. int main (){
  4.         int x = 0, pidHijo;
  5.  
  6.         pidHijo = fork ();
  7.  
  8.         if (pidHijo == 0){
  9.                 //Hijo
  10.                 printf ("Hijo: %d\n", x); //muestra 0 por pantalla
  11.                 exit (0);
  12.         }else if (pidHijo > 0){
  13.                 //Padre
  14.                 x = 1;
  15.                 printf ("Padre: %d\n", x); //muestra 1 por pantalla
  16.                 waitpid (pidHijo, NULL, 0);
  17.         }else{
  18.                 //Error
  19.                 return -1;
  20.         }
  21.  
  22.         return 0;
  23. }

Ahora en lugar de la x pon la variable global. La idea es la misma.




Bueno, espero que quien tenga el mismo problema que yo y use el google, le salga este post. xDDD


Saludos.

Última edición por GagleKas; 22/12/2009 a las 06:58
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 05:46.