Produtor Comsumidor
Autor: Cios Informática | Publicado: 2011-06-27T19:29:00-07:00

Codificação&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Este problema, chamado de Produtor-Consumidor (também conhecido como o  problema do buffer limitado), consiste em um conjunto de processos que  compartilham um mesmo buffer. Os processos chamados produtores põem informação no buffer. Os processos chamados consumidores retiram informação deste buffer.

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O mecanismo de comunicação entre processos utilizado foi a criação de  uma pipe, a qual permite que um ou mais processos troquem informações  entre si. O comando utilizado para a criação de novos processos foi fork(), que cria um processo filho retornado 0 e um processo pai retornando seu PID (Process ID).

O código do programa implementado pode ser visto abaixo.

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;unistd.h&gt;
#include &lt;math.h&gt;
 
#define CONSUMIR 0
#define ESCREVER 1
 
char* phrase="a";  //caracter a ser colocado no buffer
 
void main(){
 
int fd[2], bytesRead, prod, consum, i, j, tipo, int_rand, cont;
float rand;
 
char message[100];
 
printf("Entre com o numero de produtores:\n");
scanf("%d",&amp;prod);
 
printf("Entre com o numero de consumidores:\n");
scanf("%d",&amp;consum);
 
pipe(fd);
 
do{
 
     for(i=0; i&lt;prod; i++){
 
    if(fork()==0){
       close(fd[CONSUMIR]); // Fecha a ponta não usada
 
       //Processo produtor produz 50 ítens
 
       for(j=0; j&lt;50; j++){
           write(fd[ESCREVER],phrase,strlen(phrase));
           printf("Item produzido por %d (%d produzido pelo processo).\n",getpid(),j+1);
           sleep(1);  //Dorme ao fim de cada produção por 1 segundo
       }
 
       break;  //Ao termino da producao, pula pra fora do laco que de criacao de produtores
       close(fd[ESCREVER]);
    }
     }
 
     if(i!=prod) break;  //Se nao for o primeiro pai, pula pro fim do programa
 
     for(i=0; i&lt;consum; i++){
 
        if(fork()==0){
       close(fd[ESCREVER]);  // Fecha a ponta não usada
       cont=1; // Contador de itens consumidos pelo processo
 
       //Processo consome itens
 
       while(1){
          bytesRead=read(fd[CONSUMIR], message, 1);
          if(bytesRead&gt;0){
        printf("Lido %d item por %d (%d lido pelo processo): %s\n",bytesRead, getpid(), cont, message);
            cont++;
          }else printf("Nao ha nada para ler.");
          rand=0.0001*random();
          int_rand=rand;
          usleep(int_rand);   //Processo dorme por um tempo aleatorio ao fim de um consumo
       }
       break;
       close(fd[CONSUMIR]);
    }
     }
 
     //Processo pai produz algo antes de terminar
     write(fd[ESCREVER],phrase,strlen(phrase));
     printf("Item produzido por pai com pid %d.\n",getpid());
 
}while(0);
 
}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; O programa inicia perguntando ao usuário o número de produtores e  consumidores que ele deseja. Em seguida, é criada a pipe a ser  utilizada. Inicia-se então um bloco de código com do.  Isto foi feito para que, através de um break, um processo que já cumpriu  sua função possa pular para o fim do programa, sendo assim encerrado.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Em seguida, são criados os processos produtores. Convencionou-se que  todos os filhos criados pelo pai original, inicialmente, fossem  produtores. Cada produtor, assim que criado, produzia 50 ítens,  esperando 1 segundo entre cada produção. Ao fim do cumprimento de sua  tarefa, através de dois breaks, este processo ia para o fim do programa,  assim terminando.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Logo após foram criados os processos consumidores. Novamente  convencionou-se que todos os filhos restantes criados pelo pai original  fossem consumidores. Ao contrário dos produtores, que só produzem 50  ítems, os consumidores ficam tentando indefinidamente consumir. Esta  diferença foi feita para que o programa fosse finito (não ficasse  indefinidamente rodando). Quando o produtor não consegue mais consumir,  ele apresenta uma mensagem.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A questão das condições de disputa, neste caso, já são resolvidas  pela própria estrutura da pipe, ou seja, suas operações de escrita e  leitura garantem exclusão mútua.&nbsp;