Sincronización de procesos

Iniciado por prosebas, 24 Mayo 2021, 04:11 AM

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

prosebas


static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;


Routinas

void *routineRead(void *val)
{
   pthread_mutex_lock(&mutex);
   int fg = 0, fd;
   void *buf = malloc(MAX_SIZE * 2);
   do
   {
       fd = open(val, O_RDONLY);
       if (fd == -1)
       {
           perror("pipe");
           printf(" Se volvera a intentar despues\n");
           sleep(5);
       }
       else
           fg = 1;
   } while (fg == 0);
   read(fd, buf, MAX_SIZE * 2);
   close(fd);
   pthread_mutex_unlock(&mutex);
   return buf;
}
void *routineWrite(void *val)
{
   pthread_mutex_lock(&mutex1);
   int fg = 0, fd;
   int *time = malloc(sizeof(int));
   *time = bh.current_time;
   do
   {
       fd = open(val, O_WRONLY);
       if (fd == -1)
       {
           perror("pipe");
           printf(" Se volvera a intentar despues\n");
           sleep(5);
       }
       else
           fg = 1;
   } while (fg == 0);
   write(fd, time, MAX_SIZE);
   close(fd);
   pthread_mutex_unlock(&mutex1);
}


Mi proyecto consiste en conectar  dos procesos mediante pipes, un proceso es el controlador y el otro es agente. El controlador basicamente  se encarga de leer del pipe y enviar una respuesta, el punto es que estoy leyendo del pipe a través de un hilo, sin embargo,cada vez que se conecta un agente, el controlador lee el nombre del agente enviado por el agente y luego se crea un fifo que es el fd por donde se comunicaran ellos dos. Vale, el punto es que si llegan el agente1 y el agente2 al mismo tiempo no estoy seguro de lo que pasa pero creo que ambos entra a la sección critica y no me crea el fifo para cada agente sino  que la variable se concatena.

No supe montar la imagen aqui pero en el link pueden ver que es lo que pasa
https://ibb.co/JsgfTp5


Entonces no se  si me puedan ayudar a garantizar que si dos agente o mas se conectan a la vez atienda primero a uno y luego si siga con el otro.


   pthread_t p_read, p_write, p_time;
   sem_init(&sem, 0, 1);
   sem_init(&sem1, 0, 1);
   clean_fifo(pipe);
   int seconds = atoi(argv[6]);
   pthread_create(&p_time, NULL, routineTime, &seconds);
   do
   {
       int cont = 0;
       //p_read get the agent name from the pipe
       pthread_create(&p_read, NULL, routineRead, pipe);
       pthread_join(p_read, (void **)&agent_name);
       printf("Agente:%s\t", agent_name);
       clean_fifo(agent_name);
       //send current time
       pthread_create(&p_write, NULL, routineWrite, pipe);
       pthread_join(p_write, NULL);
       printf("pipe: %s\n", agent_name);
       //Read all the requests by an agent
       do
       {
           pthread_create(&p_read, NULL, routineRead, agent_name);
           pthread_join(p_read, (void **)&data[cont].re);
           if (data[cont].re->amount_people != 0)
               answer_request(&tree, data[cont].re, &bh);
           else
               break;
           write_pipe(fd, (struct Reserva *)data[cont].re, sizeof(Reserva), agent_name, O_WRONLY);
           cont++;
       } while (1);

   } while (1);



RayR

#1
Ese código tiene toda la apariencia de haber sido copiado de algún lado. No lo hagas, o vas a tener muchos problemas para entender estos temas.

Tu programa no funciona como multihilo, ya que, si a cada create le sigue inmediatamente un join, estás forzando a que se ejecute de forma secuencial. De todas formas, si, como planteas en tu pregunta, quieres que el controlador atienda un agente a la vez, no tiene sentido querer usar hilos. Mejor llama directamente a routineRead y routineWrite.

Omitiste demasiado código, pero parece que dentro del segundo do while usas un pipe distinto por cada proceso, como debe ser. Sin embargo, parece que al principio (línea 11 del último código) el controlador abre un pipe predefinido mediante el cual todos los agentes le envían su nombre, que luego usará para crear fifos para comunicarse con cada proceso. El problema sería que más de un proceso puede escribir en el pipe predefinido antes de que el controlador lo lea, así que cuando finalmente éste lo lee, recibe varios  juntos. Primero, el hecho de que se muestren pegados por pantalla indica que no estás enviando cadenas completas (cerradas), lo cual puede causar problemas de memoria. Si en el agente tienes algo así:

write(fd, nombre_agente, strlen(nombre_agente));

cambia el último parámetro a strlen(nombre_agente) + 1, para que también se envíe el caracter nulo. Con esto estarás mandando cadenas correctas, pero todavía queda el problema original. La cuestión es que lo que hagan los procesos externos está, en general, fuera de tu control.

Quizás lo mejor sería usar otro mecanismo (no pipes) para ese intercambio original de información, los nombres de agentes y pipes. Pero si lo quieres/tienes que hacer con pipes, lo que necesitas es delimitar de alguna forma cada mensaje. Lo más sencillo es que cada mensaje enviado al pipe predefinido (el que usas al principio para enviar el nombre del agente) sea de un tamaño fijo. Por ejemplo:

#define TAM_BUFFER 64

char nombre_agente[TAM_BUFFER];
( ...)
write(fd, nombre_agente, TAM_BUFFER);


y haces lo mismo con read. Con eso, siempre estarás leyendo exactamente un único nombre.