Jump to content

Problema - Produtor/Consumidor


h4fun

Recommended Posts

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!

Link to comment
Share on other 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...

"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Link to comment
Share on other 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??

Link to comment
Share on other 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...

"What we do for ourselves dies with us. What we do for others and the world, remains and is immortal.", Albert Pine

Blog pessoal : contém alguns puzzles, algoritmos e problemas para se resolver com programação.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.