Problema con buzones

Iniciado por snowspring, 4 Abril 2019, 18:47 PM

0 Miembros y 1 Visitante están viendo este tema.

snowspring

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:

int buzon = atoi(p_memC+334); //el buzon esta correctamente inicializado y guardado en memoria compartida
        int envio, recibo;
       
        struct tipo_mensaje
{
        long tipo;
        char mensaje[20];
}mensaje;

        while(1){

        if(*(p_memC+274) == VERDE)      //aqui se comprueba el estado del semaforo horizontal, el estado lo actualiza automaticamente luz_sem
        {
        luz_sem(HORIZONTAL, ROJO);
        strcpy(mensaje.mensaje, "HORIZ ROJO");
        mensaje.tipo = HORIZONTALROJO;
        if((envio = msgsnd(buzon, &mensaje, sizeof(struct tipo_mensaje)-sizeof(long), MSG_NOERROR))==-1)
        {
                perror("msgnd");
                raise(SIGINT);
        }
        }else if(*(p_memC+274) == ROJO){
                mensaje.tipo=VERTICALROJO;
                if((recibo=msgrcv(buzon, &mensaje, sizeof(struct tipo_mensaje)-sizeof(long), mensaje.tipo, MSG_NOERROR))==-1)
                {
                        perror("msgrcv");
                        raise(SIGINT);
                }
       
        luz_sem(HORIZONTAL, VERDE);        //esta es una funcion que esta comprobada que funciona correctamente para cambiar el semaforo de color

        }else if(*(p_memC+275) == VERDE){      //aqui se comprueba el estado del semaforo horizontal, el estado lo actualiza automaticamente luz_sem
        luz_sem(VERTICAL, ROJO);
        strcpy(mensaje.mensaje, "VERTICAL ROJO");
        mensaje.tipo = VERTICALROJO;
        if((envio = msgsnd(buzon, &mensaje, sizeof(struct tipo_mensaje)-sizeof(long), MSG_NOERROR))==-1)
        {
                perror("msgnd");
                raise(SIGINT);
        }
        }else if(*(p_memC+275) == ROJO){
                mensaje.tipo=HORIZONTALROJO;
                if((recibo=msgrcv(buzon, &mensaje, sizeof(struct tipo_mensaje)-sizeof(long), mensaje.tipo, MSG_NOERROR))==-1)
                {
                        perror("msgrcv");
                        raise(SIGINT);
                }
        luz_sem(VERTICAL, VERDE);
        }
}


Muchas gracias!

CalgaryCorpus

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.

Aqui mi perfil en LinkedIn, invitame un cafe aqui

dijsktra

#2
Cita de: 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 [...]

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....

/*
 Syncrhonized red-green semaphores

 using semaphores...

 Safety Invariant:
    0 <= one_sem + two_sem <= 1

*/

#include <pthread.h>
#include <semaphore.h>


#include <stdlib.h>  // exit
#include <stdio.h>  // print
#include <unistd.h> // sleep
sem_t one_sem;
sem_t two_sem;


void* one_thread(void *arg)
{
 for( ; 1 ; )
   {
     if (sem_wait(&one_sem))
{
 perror("sem_wait");
 exit(1);
}
     printf("one: \t\tRED\n");
     sleep(2);
     if (sem_post(&two_sem))
{
 perror("sem_post");
 exit(1);
}
     printf("one: \t\tGREEN\n");
   }
}


void* two_thread(void *arg)
{
 for( ; 1 ; )
   {
     if (sem_wait(&two_sem))
{
 perror("sem_wait");
 exit(1);
}
     printf("\t\t\t\ttwo: \t\tRED\n");
     sleep(2);
     if (sem_post(&one_sem))
{
 perror("sem_post");
 exit(1);
}
     printf("\t\t\t\ttwo: \t\tGREEN\n");
   }
}


int main(int argc, char **args)
{
 pthread_t one,two;

 sem_init(&one_sem,0,1);
 sem_init(&two_sem,0,0);
 if (pthread_create(&one, NULL, one_thread, NULL))
   {
     perror("pthread_create");
     exit(1);
   }
 if (pthread_create(&two, NULL, two_thread, NULL))
   {
     perror("pthread_create");
     exit(1);
   }

 if (!pthread_join(one,NULL))
   {
     perror("pthread_join");
     exit(1);
   }

   if (!pthread_join(two,NULL))
   {
     perror("pthread_join");
     exit(1);
   }

}



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.)
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

Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)

dijsktra

#3
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"...


/*
  Syncrhonized red-green semaphores

  using queues

  a queue can act as a distributed semaphore
*/
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#include <sys/stat.h>
#include <fcntl.h>



#include <stdlib.h>  // exit
#include <stdio.h>  // print
#include <unistd.h> // sleep

int msq1;
int msq2; // queue descriptors...


typedef struct msgbuf {
  long mtype;       /* message type, must be > 0 */
  char mtext[0];    /* message data */
} msg;
 

void one_process()
{
  struct msgbuf msg = {  1 };
  for( ; 1 ; )
    {
      if (msgrcv(msq1,(void *)&msg,sizeof(msg.mtext),0,0)==-1)
{
  perror("msgrcv");
  exit(EXIT_FAILURE);
}
      printf("one: \t\tRED\n");
      sleep(2);
      if (msgsnd(msq2,(void *)&msg,sizeof(msg.mtext),0))
{
  perror("msgsnd");
  exit(1);
}
      printf("one: \t\tGREEN\n");
    }
}


void two_process()
{
  struct msgbuf msg = { 1 };
  for( ; 1 ; )
    {
      if (msgrcv(msq2,(void *)&msg,sizeof(msg.mtext),0,0)==-1)
{
  perror("msgrcv");
  exit(EXIT_FAILURE);
}      printf("\t\t\t\ttwo: \t\tRED\n");
      sleep(2);
      if (msgsnd(msq1,(void *)&msg,sizeof(msg.mtext),0))
{
  perror("msgsnd");
  exit(1);
}
      printf("\t\t\t\ttwo: \t\tGREEN\n");
    }
}


int main(int argc, char **args)
{
  int pid;
  int msgkey =IPC_PRIVATE;
  struct msgbuf msg = { 1 };

  if ((msq1 = msgget(msgkey, IPC_CREAT | 0666 ))==-1)
    {
      perror("msgget");
      exit(EXIT_FAILURE);
    }

  if ((msq2 = msgget(msgkey, IPC_CREAT | 0666 ))==-1)
    {
      perror("msgget");
      exit(EXIT_FAILURE);
    }

  if (msgsnd(msq1,(void *)&msg,sizeof(msg.mtext),0))
    {
      perror("msgsnd");
      exit(1);
    } 
  pid = fork();
  switch (pid)
    {
    case 0 : // child
      one_process();
      break;
    default: // parent
      two_process();
    }

}









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

Si la depuración es el proceso de eliminar fallos en el software, entonces programar debe ser el proceso de ponerlos dentro. (Edsger Dijsktra)