Laboratorio 1

Neste laboratorio nossa tarefa foi implementar o problema dos produtores e consumidores no Linux utilizando pipes e processos.

Na solucao desse problema foi criado um pipe para conter os produtos produzidos esperando para serem consumidos, criada uma estrutura para representar um produto com um tamanho fixo de bytes no pipe, e utilizada a chamada fork para criar copias do processo.

A tarefa pai espera pelo processos filhos utilizando a chamada wait, entretando os filhos nunca retornarao.

Apresento abaixo o codigo da solucao do problema

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
 
#define READ 0
#define WRITE 1
 
typedef struct
{
    int i_produtor;
    int i_produto;
} produto;
 
void tarefa_pai(pid_t* produtores, int n_prod, pid_t* consumidores, int n_cons)
{
    int i;
    //aguarda por todos os processos filhos
    //aguarda pelos produtores
    for (i = 0; i < n_prod; i++)
    {
        wait(produtores[i]);
    }
    //aguarda pelos consumidores
    for (i = 0; i < n_cons; i++)
    {
        wait(consumidores[i]);
    }
    printf("Fim da tarefa\nProcesso pai saindo ...\n");
}
 
void tarefa_produtor(int* pipe_descriptor, int index, int sleep_time)
{
    int prod_count = 0;
    //fecha ponta de leitura
    close(pipe_descriptor[READ]);
    produto p;
    p.i_produtor = index;
    while(1)
    {    
        sleep(sleep_time);
        printf("Produtor %d Inserindo produto: %d\n" , index, prod_count);
        printf("============================\n");
        p.i_produto = prod_count;
        write(pipe_descriptor[WRITE], &p, sizeof(produto));
        prod_count++;
    }
}
 
void tarefa_consumidor(int* pipe_descriptor, int index, int sleep_time)
{
    produto p;
    int bytes;
    //fecha ponta de escrita
    close(pipe_descriptor[WRITE]);
    while(1)
    {
        sleep(sleep_time);
        printf("Consumidor %d" , index);
        bytes = read(pipe_descriptor[READ], &p, sizeof(produto));
        if (bytes != 0)
        {
            printf("\nRetirado: PRODUTO: %d | PRODUTOR: %d", p.i_produtor, p.i_produto);
        }
        printf("\n============================\n");
    }
}
 
int main()
{
    int pipe_descriptor[2];
    int n_prod, n_cons, i;
    int index, sleep_time;
    pid_t* prod_pids;
    pid_t* cons_pids;
    int tipo = 0;    
    /*
    tipo
    0 - pai dos processos
    1 - produtor
    2 - consumidor
    */
    printf("Numero de produtores: ");    
    scanf("%d", &n_prod);
    printf("Numero de consumidores: ");    
    scanf("%d", &n_cons);    
    //aloca espaco para guardar os pids dos produtores e consumidores
    prod_pids = malloc(sizeof(pid_t) * n_prod);
    cons_pids = malloc(sizeof(pid_t) * n_cons);
    //cria um pipe para comunicacao
    pipe(pipe_descriptor);
    srand(time(0));    
    //cria produtores
    for (i = 0; i < n_prod; i++)
    {
        //cria um valor aleatorio de sleep para este produtor
        sleep_time = random() % 20;
        prod_pids[i] = fork();
        if (prod_pids[i] == 0)
        {
            tipo = 1;
            index = i;
            break;
        }
        else if (prod_pids[i] == -1)
        {
            printf("Erro ao criar processos produtor filho\n");
            return -1;
        }
    }
    if (tipo == 0)
    {
        //cria consumidores
        for (i = 0; i < n_cons; i++)
        {
            //cria um valor aleatorio de sleep para este consumidor
            sleep_time = random() % 20;
            cons_pids[i] = fork();
            if (cons_pids[i] == 0)
            {
                tipo = 2;
                index = i;
                break;
            }
            else if (cons_pids[i] == -1)
            {
                printf("Erro ao criar processos consumidor filho\n");
                return -1;    
            }
        }
    }
    switch (tipo)
    {
        case 0:
            tarefa_pai(prod_pids, n_prod, cons_pids, n_cons);
            //libera memoria alocada
            free(prod_pids);    
            free(cons_pids);
            break;
        case 1:
            tarefa_produtor(pipe_descriptor, index, sleep_time);
            break;
        case 2:
            tarefa_consumidor(pipe_descriptor, index, sleep_time);
            break;
    }
 
    return 0;
}

Abaixo apresento uma tela de execucao do programa

execucao_lab1.png

Verificando a tela de saida da execucao e possivel verificar o intercalamento de execucao dos programas que acabam tendo suas saidas intercaladas.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License