O problema em questão possui um grau de abstração tão grande que pode ser aplicado nos mais diversificados setores, como a agricultura.
Neste problema, um conjunto de processos Produtores suprem de mensagens para um conjunto de processos consumidores. Estes processos compartilham uma fila de buffer comum onde mensagens são depositados pelos produtores e removidas pelos consumidores. Todos os processos são assíncronos no sentido de que produtores e consumidores podem depositar e remover mensagens a qualquer tempo. Duas condições tem de ser satisfeitas: Nenhum processo consumidor pode remover uma mensagem quando o buffer estiver vazio e nenhum processo produtor pode depositar uma mensagem com o buffer cheio.
Problemas de integridade podem aparecer se múltiplos consumidores (ou produtores) tentarem remover (ou inserir) mensagens no buffer ao mesmo tempo. Por exemplo, as estruturas de dados associadas (ponteiros para buffers) podem não ser atualizados consistentemente, ou dois produtores tentam colocar mensagens no mesmo buffer. O acesso ao buffer e as estruturas de dados associadas devem constituir uma seção crítica.
Bibliografia: http://www.jr.eti.br
Utilizei pipes na solução do problema, seguindo a proposta feita pelo Professor. Com o tempo extra fornecido pelo Professor, foi possível completar o código do programa. Os testes apresentaram bons resultados, como mostra o screenshot após o código. Poderia ter sido mais bem implementada a questão dos tempos entre produção e consumo dos produtos - incluindo tempos randômicos, por exemplo -, para refletir melhor uma situação real.
Abaixo, o código do programa:
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#define NUMBER_PRODUCERS 2
#define NUMBER_CONSUMERS 2
#define NUMBER_PIPES 20
#define NUMBER_ITEMS 10 //number of items per pipe
#define TIME_PRODUCE 2 //time to make a new product
#define TIME_CONSUME 3 //time to consume a product
//defines which side of the pipe reads/writes
#define READ 0
#define WRITE 1
#define TRUE 1
typedef struct product product;
struct product {
int prod_id;
pid_t product_id;
};
int fd[2];
void cons_product(int,int);
void producer() {
product new;
int i;
close(fd[READ]);
for (i=0; i<NUMBER_ITEMS; i++) {
/*new = prod_product(i);*/
//BEGINS prod_product
new.prod_id = i;
new.product_id = getpid();
printf("Process #%d produces product #%d.\n",new.product_id, new.prod_id);
sleep(TIME_PRODUCE);
//ENDS prod_product
write(fd[WRITE], &new, sizeof(product));
}
close(fd[WRITE]);
}
void consumer() {
product aux;
int i;
int ok_process;
close(fd[WRITE]);
while(TRUE) {
ok_process = read(fd[READ], &aux, sizeof(product));
if (ok_process < 0) printf("Could not read from pipe.\n");
else {
if (ok_process == 0) printf("Empty pipe.\n");
else cons_product(aux.product_id, aux.prod_id);
}
}
close(fd[READ]);
}
product prod_product(int id){
product new;
new.prod_id = id;
new.product_id = getpid();
printf("Process #%d produces product #%d.\n",new.product_id, id);
sleep(TIME_PRODUCE);
return new;
}
void cons_product(int producer_process, int index){
int consumer_number = getpid();
printf("Process #%d consumes product #%d from producer #%d.\n", consumer_number, index, producer_process);
sleep(TIME_CONSUME);
}
void call_new_producer(){
int ok_process;
ok_process = fork();
if (ok_process == -1) {
printf("Could not create a new process.");
exit(-1);
}
else if (ok_process == 0) producer();
}
void call_new_consumer(){
int ok_process;
ok_process = fork();
if (ok_process == -1) {
printf("Could not create a new process.");
exit(-1);
}
else consumer();
}
int main() {
int i;
pipe(fd);
for (i=0; i<NUMBER_PRODUCERS; i++) call_new_producer();
for (i=0; i<NUMBER_CONSUMERS; i++) call_new_consumer();
return 0;
}