Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: snowspring en 4 Abril 2019, 18:47 pm



Título: Problema con buzones
Publicado por: snowspring en 4 Abril 2019, 18:47 pm
Hola!
Estaba haciendo un ejercicio en el cual hay que sincronizar varios procesos y que estos procesos sigan sincronizandose (en este caso los procesos son unos semaforos que tienen que ir cambiando de color de forma logica osea cuando uno este en verde el otro no puede estar en verde y viceversa) hasta que se pulse ctrl-c.
El caso es que  mi idea era realizar esta sincronizacion con un buzon IPC pero el problema viene que despues de la primera interaccion del bucle infinito el programa ya no vuelve a cambiar de color los semaforos, es decir, si inicialmente los semaforos estan uno a verde y otro a rojo  el programa entra en el bucle y cambia el verde a rojo y el rojo a verde SOLO 1 vez (el objetivo es que este cambio se produzca continuamente).
Dejo aqui el codigo:

Código
  1. int buzon = atoi(p_memC+334); //el buzon esta correctamente inicializado y guardado en memoria compartida
  2.        int envio, recibo;
  3.  
  4.        struct tipo_mensaje
  5. {
  6.        long tipo;
  7.        char mensaje[20];
  8. }mensaje;
  9.  
  10.        while(1){
  11.  
  12.        if(*(p_memC+274) == VERDE)      //aqui se comprueba el estado del semaforo horizontal, el estado lo actualiza automaticamente luz_sem
  13.        {
  14.        luz_sem(HORIZONTAL, ROJO);
  15.        strcpy(mensaje.mensaje, "HORIZ ROJO");
  16.        mensaje.tipo = HORIZONTALROJO;
  17.        if((envio = msgsnd(buzon, &mensaje, sizeof(struct tipo_mensaje)-sizeof(long), MSG_NOERROR))==-1)
  18.        {
  19.                perror("msgnd");
  20.                raise(SIGINT);
  21.        }
  22.        }else if(*(p_memC+274) == ROJO){
  23.                mensaje.tipo=VERTICALROJO;
  24.                if((recibo=msgrcv(buzon, &mensaje, sizeof(struct tipo_mensaje)-sizeof(long), mensaje.tipo, MSG_NOERROR))==-1)
  25.                {
  26.                        perror("msgrcv");
  27.                        raise(SIGINT);
  28.                }
  29.  
  30.        luz_sem(HORIZONTAL, VERDE);        //esta es una funcion que esta comprobada que funciona correctamente para cambiar el semaforo de color
  31.  
  32.        }else if(*(p_memC+275) == VERDE){      //aqui se comprueba el estado del semaforo horizontal, el estado lo actualiza automaticamente luz_sem
  33.         luz_sem(VERTICAL, ROJO);
  34.         strcpy(mensaje.mensaje, "VERTICAL ROJO");
  35.         mensaje.tipo = VERTICALROJO;
  36.         if((envio = msgsnd(buzon, &mensaje, sizeof(struct tipo_mensaje)-sizeof(long), MSG_NOERROR))==-1)
  37.         {
  38.                perror("msgnd");
  39.                raise(SIGINT);
  40.         }
  41.        }else if(*(p_memC+275) == ROJO){
  42.                mensaje.tipo=HORIZONTALROJO;
  43.                if((recibo=msgrcv(buzon, &mensaje, sizeof(struct tipo_mensaje)-sizeof(long), mensaje.tipo, MSG_NOERROR))==-1)
  44.                {
  45.                        perror("msgrcv");
  46.                        raise(SIGINT);
  47.                }
  48.         luz_sem(VERTICAL, VERDE);
  49.        }
  50. }

Muchas gracias!


Título: Re: Problema con buzones
Publicado por: CalgaryCorpus en 5 Abril 2019, 16:11 pm
Existe un valor distinto de verde o rojo para los semaforos?

Los primeros 2 ifs me dan la impresion que cubren todos los casos para 1 semaforo y por lo tanto los otros 2 ifs nunca se van a ejecutar.



Título: Re: Problema con buzones
Publicado por: dijsktra en 8 Abril 2019, 15:14 pm
Hola!
Estaba haciendo un ejercicio en el cual hay que sincronizar varios procesos y que estos procesos sigan sincronizandose (en este caso los procesos son unos semaforos que tienen que ir cambiando de color de forma logica osea cuando uno este en verde el otro no puede estar en verde y viceversa) hasta que se pulse ctrl-c.
El caso es que  mi idea era realizar esta sincronizacion con un buzon IPC [...]

Muchas gracias!

A ver, la forma "natural" de hacerlo es con semáforos, no con lo que tu llamas "buzones"... (Creo que con lo que te refieres a eso es a colas, pero bueno...) En cuanto pueda, hago una solución de ese modo ;D

Aquí  hay una propuesta de simulación. Creo que deberías empezar por threads, en vez de , como creo, haces con IPC y fork(), al estar incompleto el código, no puedo interpretar....

Código
  1. /*
  2.   Syncrhonized red-green semaphores
  3.  
  4.   using semaphores...
  5.  
  6.   Safety Invariant:
  7.      0 <= one_sem + two_sem <= 1
  8.  
  9. */
  10.  
  11. #include <pthread.h>
  12. #include <semaphore.h>
  13.  
  14.  
  15. #include <stdlib.h>  // exit
  16. #include <stdio.h>  // print
  17. #include <unistd.h> // sleep
  18. sem_t one_sem;
  19. sem_t two_sem;
  20.  
  21.  
  22. void* one_thread(void *arg)
  23. {
  24.  for( ; 1 ; )
  25.    {
  26.      if (sem_wait(&one_sem))
  27. {
  28.  perror("sem_wait");
  29.  exit(1);
  30. }
  31.      printf("one: \t\tRED\n");
  32.      sleep(2);
  33.      if (sem_post(&two_sem))
  34. {
  35.  perror("sem_post");
  36.  exit(1);
  37. }
  38.      printf("one: \t\tGREEN\n");
  39.    }
  40. }
  41.  
  42.  
  43. void* two_thread(void *arg)
  44. {
  45.  for( ; 1 ; )
  46.    {
  47.      if (sem_wait(&two_sem))
  48. {
  49.  perror("sem_wait");
  50.  exit(1);
  51. }
  52.      printf("\t\t\t\ttwo: \t\tRED\n");
  53.      sleep(2);
  54.      if (sem_post(&one_sem))
  55. {
  56.  perror("sem_post");
  57.  exit(1);
  58. }
  59.      printf("\t\t\t\ttwo: \t\tGREEN\n");
  60.    }
  61. }
  62.  
  63.  
  64. int main(int argc, char **args)
  65. {
  66.  pthread_t one,two;
  67.  
  68.  sem_init(&one_sem,0,1);
  69.  sem_init(&two_sem,0,0);
  70.  if (pthread_create(&one, NULL, one_thread, NULL))
  71.    {
  72.      perror("pthread_create");
  73.      exit(1);
  74.    }
  75.  if (pthread_create(&two, NULL, two_thread, NULL))
  76.    {
  77.      perror("pthread_create");
  78.      exit(1);
  79.    }
  80.  
  81.  if (!pthread_join(one,NULL))
  82.    {
  83.      perror("pthread_join");
  84.      exit(1);
  85.    }
  86.  
  87.    if (!pthread_join(two,NULL))
  88.    {
  89.      perror("pthread_join");
  90.      exit(1);
  91.    }
  92.  
  93. }
  94.  


Y la salida, (el efecto temporal no sale en esta página estática Web, claro. Deberias ver que se sincronizan al mismo tiempo. Correlo en tu terminal.)
Código:
gcc redgreen.c -lpthread -o main && ./main
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED


Título: Re: Problema con buzones [con queues]
Publicado por: dijsktra en 10 Abril 2019, 15:44 pm
Lo prometido es deuda. Aqui tienes una implementación de sincronización con colas System V.

Comentarios
  • Podemos emular una especie de semáforo distribuido con colas. Las operaciones P(s) y V(s) son las correspondeintes a rcv(q) y snd(q). Eso si, expresado en C, es un poco críptico, ya que tenemos que ver siempre el retorno de la llamada al sistema
  • Al ser utilizado como señalización, el mensaje no precisa de datos. no se precisa comunicar ningún dato, el mismo acto de envío y recepción es suficiente. De ahí que el msg.txt sea de tamñao 0, no es necesario poner "LUZ VERDE" o "LUZ ROJA"...



Código
  1. /*
  2.   Syncrhonized red-green semaphores
  3.  
  4.   using queues
  5.  
  6.   a queue can act as a distributed semaphore
  7. */
  8. #include <sys/types.h>
  9. #include <sys/ipc.h>
  10. #include <sys/msg.h>
  11.  
  12. #include <sys/stat.h>
  13. #include <fcntl.h>
  14.  
  15.  
  16.  
  17. #include <stdlib.h>  // exit
  18. #include <stdio.h>  // print
  19. #include <unistd.h> // sleep
  20.  
  21. int msq1;
  22. int msq2; // queue descriptors...
  23.  
  24.  
  25. typedef struct msgbuf {
  26.  long mtype;       /* message type, must be > 0 */
  27.  char mtext[0];    /* message data */
  28. } msg;
  29.  
  30.  
  31. void one_process()
  32. {
  33.  struct msgbuf msg = {  1 };
  34.  for( ; 1 ; )
  35.    {
  36.      if (msgrcv(msq1,(void *)&msg,sizeof(msg.mtext),0,0)==-1)
  37. {
  38.  perror("msgrcv");
  39.  exit(EXIT_FAILURE);
  40. }
  41.      printf("one: \t\tRED\n");
  42.      sleep(2);
  43.      if (msgsnd(msq2,(void *)&msg,sizeof(msg.mtext),0))
  44. {
  45.  perror("msgsnd");
  46.  exit(1);
  47. }
  48.      printf("one: \t\tGREEN\n");
  49.    }
  50. }
  51.  
  52.  
  53. void two_process()
  54. {
  55.  struct msgbuf msg = { 1 };
  56.  for( ; 1 ; )
  57.    {
  58.      if (msgrcv(msq2,(void *)&msg,sizeof(msg.mtext),0,0)==-1)
  59. {
  60.  perror("msgrcv");
  61.  exit(EXIT_FAILURE);
  62. }      printf("\t\t\t\ttwo: \t\tRED\n");
  63.      sleep(2);
  64.      if (msgsnd(msq1,(void *)&msg,sizeof(msg.mtext),0))
  65. {
  66.  perror("msgsnd");
  67.  exit(1);
  68. }
  69.      printf("\t\t\t\ttwo: \t\tGREEN\n");
  70.    }
  71. }
  72.  
  73.  
  74. int main(int argc, char **args)
  75. {
  76.  int pid;
  77.  int msgkey =IPC_PRIVATE;
  78.  struct msgbuf msg = { 1 };
  79.  
  80.  if ((msq1 = msgget(msgkey, IPC_CREAT | 0666 ))==-1)
  81.    {
  82.      perror("msgget");
  83.      exit(EXIT_FAILURE);
  84.    }
  85.  
  86.  if ((msq2 = msgget(msgkey, IPC_CREAT | 0666 ))==-1)
  87.    {
  88.      perror("msgget");
  89.      exit(EXIT_FAILURE);
  90.    }
  91.  
  92.  if (msgsnd(msq1,(void *)&msg,sizeof(msg.mtext),0))
  93.    {
  94.      perror("msgsnd");
  95.      exit(1);
  96.    }  
  97.  pid = fork();
  98.  switch (pid)
  99.    {
  100.    case 0 : // child
  101.      one_process();
  102.      break;
  103.    default: // parent
  104.      two_process();
  105.    }
  106.  
  107. }
  108.  








Código:
 gcc redgreen.que.c -o main && ./main
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED
two: GREEN
one: RED
one: GREEN
two: RED