• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

h4fun

Problema - Produtor/Consumidor

6 mensagens neste tópico

Pessoal,

Estou com um problema em mãos e gostaria de obter uma ajuda vossa se possível.

Necessito de criar um programa que me faça a gestão (através de semáforos) de acesso à memoria partilhada.

Tenho o codigo a funcionar , mas para um produtor , consumidor.... como posso alterar o codigo para "n" produtores e "n" consumidores?

Para uma mais facil compreensão, deixo o codigo a seguir:

#include "sema.h"

/* definicao de constantes: produtor - consumidor ______________________*/
#define N 5 				/* numeros de dados guardados em simultaneo */
#define NVEZES 10   		/* numero de dados produzidos */
#define SLEEPTIME 1   	/* tempo de espera */

/* definicao de constantes: memoria partilhada ________________________ */
#define SHMKEY (key_t) 0x10

/* declaracao de funcoes: produtor - consumidor _______________________ */
void produz();
void consome();
void produtor();
void consumidor();

/* declaracao de variaveis globais: semaforos _________________________ */
semaphore empty, full, mutex;

/* declaracao de variaveis globais: memoria partilhada	_______________ */
int shmid;
int *ptr;


//int buf[N];
int in=0,out=0;

main ()
{
  /* declaracao de variaveis locais: produtor-consumidor	*/
  int		pid;		/* process ID's	*/

  /* declaracao de variaveis locais: memoria partilhada	*/
  char *addr;

  printf("\nProblema do produtor / consumidor \n");
  printf(" 1 produtor para 1 consumidor \n");
  
  /* inicializacao: semaforos */
  empty = init_sem(N);		/* posicoes vazias (inicio = N) */
  mutex = init_sem(1);		/* exclusao mutua */
  full = init_sem(0);		/* posicoes cheias (inicio = 0)	*/

  /* inicializacao: memoria partilhada */

  shmid = shmget(SHMKEY, 128,0777|IPC_CREAT);
  addr = (char*)shmat(shmid, 0, 0);
  ptr = (int*)addr;

  in = out = 0;

  pid = fork ();
  switch(pid)
  {
      case -1:			/* erro	no fork	*/
	perror("Erro na chamada a funcao fork.");
	exit(1);
	break;

      case 0:			/* processo filho */
	consumidor();
	exit(0);
	break;

      default:			/* processo pai	*/
	produtor();
	wait(NULL);
	printf("\n");

	/* Liberta: semaforos */
	rel_sem(mutex);
	rel_sem(full);
	rel_sem(empty);

	/* liberta: memoria partilhada */

	shmdt (addr);
	shmctl (shmid, IPC_RMID,NULL);

  }	/* fim switch */
} /* fim main */

/* produtor - consumidor _______________________________________________*/

void produz()
{
   int item;

   sleep(SLEEPTIME);
   srand ((unsigned int) time ((time_t) NULL));
   item = rand () % 10;

   /* insere item na memoria partilhada */
   
   *(ptr+in)= rand ()%10;
   printf("Produzi o item : %d\n",*(ptr+in)); 
   		
//  buf[in] = item;
   
//   printf(" %d produz \t%d para o endereco %d\n", getpid(), buf[in], in);
   in = (in + 1) % N;
}

void consome()
{
   int item = 0;

   sleep(SLEEPTIME);
   
   /* ... vai buscar item a memoria partilhada */
   
    item = *(ptr+out);
    printf("Consumi o item : %d\n",*(ptr+out)); 
  

  // item = buf[out];
   
//  printf("%d consome \t%d do endereco %d\n", getpid(), buf[out], out);
   out = (out + 1) % N;  
}

void produtor()
{
   int i;

   for(i = 0; i < NVEZES; i++)
   {
      P(empty);
      P(mutex);		
      produz();
      V(mutex);		   
      V(full);		
   }
}

void consumidor()
{
   int i;

   for(i = 0; i < NVEZES; i++)
   {
      P(full);	
      P(mutex);		
      consome();
      V(mutex);		
      V(empty);			
   }
}

/* _____________________________________________________________________*/

Alguém me pode dar umas luzes??

Obrigado!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se bem me lembro, o truque é inicializar o semaforo a N e não a 0 ou 1... já não me lembro bem. O meu prof falou nisso numa teórica. O site tá em baixo senão ia ver os slides...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

tenho o mesmo problema... como fazer multiplos fork para criar varios filhos?? Eu consegui criando filhos dos filhos mas será essa a melhor opção?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tipo de se eu faço

pid=fork();
pid=fork();

antes do switch ou do if

faz-me dois consumidores e dois produtores

só fazendo

  pid = fork ();
  switch(pid)
  {
      case -1:			/* erro	no fork	*/
	perror("Erro na chamada a funcao fork.");
	exit(1);
	break;

      case 0:			/* processo filho */
	pid=fork();
                consumidor();
	exit(0);
	break;
      case 1:
                consumidor();
	exit(0);
	break;

é que fico com 2 consumidores e dois produtores... se puser o segundo pid=fork() for antes do switch mesmo tendo la o case 1 com consumidor ele cria-me dois de cada... o problema é que assim os filhos são criados sequencialmente em vez de todos de uma vez... isso não poderá causa problemas de sincronização??

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

devias ir ao manual do fork  ("man 2 fork" na linha de comandos). O fork cria 2 processos, no processo filho devolve 0, no processo pai devolve o process id do filho que dificilmente é "1". Ao usar um switch tens de fazer como o h4fun, "default:"  ...

quanto a duvida dos semaforos nao sei responder... ainda não estudei isso ;)  mas podem ver http://paginas.fe.up.pt/~jsilva/so/t_06.pdf  fala aí nisso, mas não sei se ajuda muito...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora