Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: prosebas en 24 Mayo 2021, 04:11 am



Título: Sincronización de procesos
Publicado por: prosebas en 24 Mayo 2021, 04:11 am
Código
  1. static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  2. static pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
  3.  

Routinas
Código
  1. void *routineRead(void *val)
  2. {
  3.    pthread_mutex_lock(&mutex);
  4.    int fg = 0, fd;
  5.    void *buf = malloc(MAX_SIZE * 2);
  6.    do
  7.    {
  8.        fd = open(val, O_RDONLY);
  9.        if (fd == -1)
  10.        {
  11.            perror("pipe");
  12.            printf(" Se volvera a intentar despues\n");
  13.            sleep(5);
  14.        }
  15.        else
  16.            fg = 1;
  17.    } while (fg == 0);
  18.    read(fd, buf, MAX_SIZE * 2);
  19.    close(fd);
  20.    pthread_mutex_unlock(&mutex);
  21.    return buf;
  22. }
  23. void *routineWrite(void *val)
  24. {
  25.    pthread_mutex_lock(&mutex1);
  26.    int fg = 0, fd;
  27.    int *time = malloc(sizeof(int));
  28.    *time = bh.current_time;
  29.    do
  30.    {
  31.        fd = open(val, O_WRONLY);
  32.        if (fd == -1)
  33.        {
  34.            perror("pipe");
  35.            printf(" Se volvera a intentar despues\n");
  36.            sleep(5);
  37.        }
  38.        else
  39.            fg = 1;
  40.    } while (fg == 0);
  41.    write(fd, time, MAX_SIZE);
  42.    close(fd);
  43.    pthread_mutex_unlock(&mutex1);
  44. }
  45.  

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.

Código
  1.    pthread_t p_read, p_write, p_time;
  2.    sem_init(&sem, 0, 1);
  3.    sem_init(&sem1, 0, 1);
  4.    clean_fifo(pipe);
  5.    int seconds = atoi(argv[6]);
  6.    pthread_create(&p_time, NULL, routineTime, &seconds);
  7.    do
  8.    {
  9.        int cont = 0;
  10.        //p_read get the agent name from the pipe
  11.        pthread_create(&p_read, NULL, routineRead, pipe);
  12.        pthread_join(p_read, (void **)&agent_name);
  13.        printf("Agente:%s\t", agent_name);
  14.        clean_fifo(agent_name);
  15.        //send current time
  16.        pthread_create(&p_write, NULL, routineWrite, pipe);
  17.        pthread_join(p_write, NULL);
  18.        printf("pipe: %s\n", agent_name);
  19.        //Read all the requests by an agent
  20.        do
  21.        {
  22.            pthread_create(&p_read, NULL, routineRead, agent_name);
  23.            pthread_join(p_read, (void **)&data[cont].re);
  24.            if (data[cont].re->amount_people != 0)
  25.                answer_request(&tree, data[cont].re, &bh);
  26.            else
  27.                break;
  28.            write_pipe(fd, (struct Reserva *)data[cont].re, sizeof(Reserva), agent_name, O_WRONLY);
  29.            cont++;
  30.        } while (1);
  31.  
  32.    } while (1);
  33.  



Título: Re: Sincronización de procesos
Publicado por: RayR en 25 Mayo 2021, 01:10 am
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í:

Código
  1. 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:

Código
  1. #define TAM_BUFFER 64
  2.  
  3. char nombre_agente[TAM_BUFFER];
  4. ( ...)
  5. write(fd, nombre_agente, TAM_BUFFER);

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