Producer consumer c (within linux)

Contenu du snippet

/***********************************************************************

But : résoudre le problème de Producteurs/consommateurs
Description : Ce programme lance (crée) un nombre de producteurs qui écirvent dans
un tampon de taille N et lance un autre nombre de consommateurs qui consomme
les objets résidant dans le tampon...
Cet exemple est sans animation....


*
                                                                                                                                              • /


Billal Begueradj.
University of Bejaia

Source / Exemple :

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <wait.h>

#include <sys/ipc.h> // la bibliothèque des ipc : IPC_CREAT, IPC_EXCL, ...
#include <sys/sem.h> // La bibliothèque des sémaphores...
#include <sys/shm.h> // La bibliothèque de la mémoire partgeé...

#include "ccrt.h"

#define Max 10// le nombre maximal de cases dans le tampon...

// les structures t_case et t_info
typedef struct {// cette structure représente le contenue d'une case d'un tampon (contenant N cases)...
 int  nb_rand;
 char ch_rand;
} t_case; 

typedef struct {
 int i,j; // i: indice de la case où sera la production. j: indice de la case où sera la consommation.
 int plein;// nombre indiquant le nombre de cases pleines...
} t_info;

//les prototypes des fonctions..
void producteur(int); // le code du producteur
void consommateur(int); //le code du consommateur

void produire (t_case*); // la fonction qui simule la production
void consommer (t_case); // la fonction qui simule la consommation

void mettre(t_case);
void prendre(t_case*);

//fonctions de dessin...
void tampon(int n);
void affiche_prod(int np);
void affiche_cons(int nc);
void cacher_prod(int np);
void cacher_cons(int nc);

//les variables globales
t_case*  mem1;// le premier segement sera vu comme un tabelau de t_case
t_info*  mem2;// le deuxième segement sera vu comme un tabelau de t_case
int  nb_cases; // la taille du tampon
int  i_mutex; // mutex pour la variable i (de mem2)
int  j_mutex; // mutex pour la variable j (de mem2)
int  plein_mutex; // mutex pour la variable plein (de mem2)
int  file_prod;   // sméphore qui représente la files des producteurs bloqués
int  file_cons;   // sméphore qui représente la files des producteurs bloqués
time_t  t0;
struct sembuf  op_v= {0, +1, SEM_UNDO}; // l'opération V sur les sémaphores
struct sembuf  op_p= {0, -1, SEM_UNDO}; // l'opération P sur les sémaphores

//La fonction principale...
int main (){
 pid_t  f;
 int  id_mem1, id_mem2; //identifiant des deux segments de mémoires partagées...
 const int taille1=0x6400, taille2=0x400; // les tailles des deux mémoires partagées...
 key_t  cle;// une clé...
 int  nb_p; // nombre de producteurs...
 int  nb_c; // nombre de consommateurs...
 int  num_p,num_c;// les numéros des producteurs et des consommateurs
 int  i, st;
 ushort  init_sem1[]={1}, init_sem0[]={0};

 
 time(&t0); // la date du début de l'exécution du père...

 //génération de la clé...
 if ( (cle = ftok (".", 'a')) == -1){
  perror ("ftok");
  return -1;
 }
 //génération du segment de la première mémoire partagée...
 id_mem1 = shmget (cle, taille1, IPC_CREAT|IPC_EXCL|0666);
 if (id_mem1 == -1){
  perror ("shmget - 1");
  return -1;
 }

 //génération de la clé...
 if ( (cle = ftok (".", 'b')) == -1){
  perror ("ftok");
  return -1;
 }
 //génération du segment de la deuxième mémoire partagée...
 id_mem2 = shmget (cle, taille2, IPC_CREAT|IPC_EXCL|0666);
 if (id_mem2 == -1){
  perror ("shmget - 2");
  return -1;
 }

 //génération de la clé...
 if ( (cle = ftok (".", 'c')) == -1){
  perror ("ftok");
  return -1;
 }
 //génération du i_mutex...
 i_mutex = semget( cle, 1 ,IPC_CREAT|IPC_EXCL|0666);
 if (i_mutex == -1){
  perror ("semget - 1");
  return -1;
 }

 //génération de la clé...
 if ( (cle = ftok (".", 'd')) == -1){
  perror ("ftok");
  return -1;
 }
 //génération du j_mutex...
 j_mutex = semget( cle, 1 ,IPC_CREAT|IPC_EXCL|0666);
 if (j_mutex == -1){
  perror ("semget - 2");
  return -1;
 }

 //génération de la clé...
 if ( (cle = ftok (".", 'e')) == -1){
  perror ("ftok");
  return -1;
 }
 //génération du plein_mutex...
 plein_mutex = semget( cle, 1 ,IPC_CREAT|IPC_EXCL|0666);
 if (plein_mutex == -1){
  perror ("semget - 3");
  return -1;
 }

 //génération de la clé...
 if ( (cle = ftok (".", 'f')) == -1){
  perror ("ftok");
  return -1;
 }
 //génération du file_prod...
 file_prod = semget( cle, 1 ,IPC_CREAT|IPC_EXCL|0666);
 if (file_prod == -1){
  perror ("semget - 4");
  return -1;
 }

 //génération de la clé...
 if ( (cle = ftok (".", 'g')) == -1){
  perror ("ftok");
  return -1;
 }
 //génération du file_cons...
 file_cons = semget( cle, 1 ,IPC_CREAT|IPC_EXCL|0666);
 if (file_cons == -1){
  perror ("semget - 5");
  return -1;
 }

 if (semctl (i_mutex, 0, SETALL, init_sem1)==-1){
  perror ("semctl");
  return -1;
 }
 if (semctl (j_mutex, 0, SETALL, init_sem1)==-1){
  perror ("semctl");
  return -1;
 }
 if (semctl (plein_mutex, 0, SETALL, init_sem1)==-1){
  perror ("semctl");
  return -1;
 }
 if (semctl (file_prod, 0, SETALL, init_sem0)==-1){
  perror ("semctl");
  return -1;
 }
 if (semctl (file_cons, 0, SETALL, init_sem0)==-1){
  perror ("semctl");
  return -1;
 }
 
 mem1 = shmat (id_mem1, 0, 0); // le premier segement sera vu comme un tabelau de t_case
 mem2 = shmat (id_mem2, 0, 0); // le deuxième segement sera vu comme une case t_info

 //initialisation des informations de la mémoire mem2
 mem2->i=0;
 mem2->j=0;
 mem2->plein=0;

 //informations générales à introduire par l'utilisateur...
 printf ("nDonnez le nombre de cases du Tampon (entre 1 et %d) : ", Max);
 while (1){
  scanf ("%d", &nb_cases);getchar();
  if ((nb_cases<1)||(nb_cases>Max))
   printf ("Erreur : vous deviez introduire un nombre entre 1 et %d : ", Max);
  else
   break;
 }
 printf ("nDonnez le nombre de producteurs (>=1) : ");
 while (1){
  scanf ("%d", &nb_p);getchar();
  if (nb_p<1)
   printf ("Erreur : vous deviez introduire un nombre >= 1");
  else
   break;
 }
 printf ("nDonnez le nombre de consommateurs (>=1) : ");
 while (1){
  scanf ("%d", &nb_c);getchar();
  if (nb_c<1)
   printf ("Erreur : vous deviez introduire un nombre >= 1");
  else
   break;
 }

 // Dessiner l'interface...
 ClrScr();
 tampon(nb_cases);
 printf ("n");

 // la création des producteurs
 num_p = 1;
 for (i=0; i<nb_p; i++){
  srand (time(NULL));//assurer d'avoir des nombres aléatoires pour les différents producteurs
  f = fork();
  if (f==-1){
   perror ("fork- producteur");
   return -1;
  }
  if (f==0){//la zone des producteurs....
   producteur(num_p);
   return 0;
  }// fin de la zone des producteurs....
  num_p++;// avoir le prochain numéro de producteur
  sleep(1);// attendre une seconde avant la prochaine création d'un fils
 }

 // la création des consommateurs
 num_c = 1;
 for (i=0; i<nb_c; i++){
  srand (time(NULL));//assurer d'avoir des nombres aléatoires pour les différents consommateurs
  f = fork();
  if (f==-1){
   perror ("fork- producteur");
   return -1;
  }
  if (f==0){//la zone des consommateurs....
   consommateur(num_c);
   return 0;
  }// fin de la zone des consommateurs....
  num_c++;// avoir le prochain numéro de producteur
  sleep(1);// attendre une seconde avant la prochaine création d'un fils
 }

 //attendre tous les fils...
 for (i=0; i<nb_p+nb_c; i++)
  wait(&st);

 // détachement des deux segments de mémoire partagée...
 shmdt (mem1);
 shmdt (mem2);

 if (shmctl (id_mem1, IPC_RMID, 0) == -1){ // suppression de la première mémoire partagée...
  perror ("shmctl - suppression 1");
  return -1;
 }
 if (shmctl (id_mem2, IPC_RMID, 0) == -1){ // suppression de la première mémoire partagée...
  perror ("shmctl - suppression 2");
  return -1;
 }
 if (semctl (i_mutex, 0, IPC_RMID, 0) == -1){ // la libération du sémaphore...
  perror ("semctl - 1");
  return -1;
 }
 if (semctl (j_mutex, 0, IPC_RMID, 0) == -1){ // la libération du sémaphore...
  perror ("semctl - 1");
  return -1;
 }
 if (semctl (plein_mutex, 0, IPC_RMID, 0) == -1){ // la libération du sémaphore...
  perror ("semctl - 1");
  return -1;
 }
 if (semctl (file_prod, 0, IPC_RMID, 0) == -1){ // la libération du sémaphore...
  perror ("semctl - 1");
  return -1;
 }
 if (semctl (file_cons, 0, IPC_RMID, 0) == -1){ // la libération du sémaphore...
  perror ("semctl - 1");
  return -1;
 }

 TextColor (BLACK);
 TextBackground(WHITE);
 ClrScr();
 GotoXY (1,1);
 return 0;
}// fin de la fonction principale...

//L'implémentation des fonctions

void producteur(int np){//le porducteur...
 t_case c;
 time_t tc;
 time(&tc);
 affiche_prod(np);
 //srand (time(NULL));
 while (1){
  TextBackground (WHITE);
  GotoXY(15, 3+(np-1)*3); printf ("                                    n");
  time(&tc);

  TextBackground (WHITE);
  TextColor (BLACK);
  GotoXY(15, 3+(np-1)*3); printf ("t:%d | s'endormirn", tc-t0);
  sleep (rand()%3);
  TextBackground (WHITE);
  TextColor (BLACK);
  GotoXY(15, 3+(np-1)*3); printf ("                 n");

  time(&tc);
  TextBackground (WHITE);
  TextColor (BLACK);
  GotoXY(15, 3+(np-1)*3); printf ("t:%d | produiren", tc-t0);
  produire(&c);// production d'un objet...

  sleep (rand()%2);
  TextBackground (WHITE);
  TextColor (BLACK);
  GotoXY(15, 3+(np-1)*3); printf ("                        n");
  time(&tc);

   TextBackground (WHITE);
   TextColor (BLACK);  
   GotoXY(15, 3+(np-1)*3); printf ("t:%d | Mettre dans le tamponn", tc-t0);
   mettre (c);
   
  time(&tc);
  TextBackground (WHITE);
  TextColor (BLACK);
  GotoXY(15, 3+(np-1)*3); printf ("t:%d | objet mis  dans le tampon    n", tc-t0); 
  if ((rand()%5) == 0){
   TextBackground (WHITE);
   TextColor (BLACK);
   GotoXY(15, 3+(np-1)*3); printf ("                                  n");
   break;
  }
 }
 time(&tc);
 cacher_prod(np);
}// fin producteur...

void consommateur(int nc){//le consommateur...
 t_case c;
 time_t tc;
 time(&tc);
 affiche_cons(nc);
 //srand (time(NULL));
 while (1){
  TextBackground (WHITE);
  TextColor (BLACK);
  GotoXY(70, 3+(nc-1)*3); printf ("                             n");

  time(&tc);
  
  TextBackground (WHITE);
  TextColor (BLACK);
  GotoXY(70, 3+(nc-1)*3); printf ("t:%d | s'endormirn", tc-t0);
  sleep (rand()%3);

  time(&tc);
   TextBackground (WHITE);
   TextColor (BLACK);
   GotoXY(70, 3+(nc-1)*3); printf ("t:%d | prendre un objetn", tc-t0);

   prendre (&c);
  

  time(&tc);
  TextBackground (WHITE);
  TextColor (BLACK);
  GotoXY(70, 3+(nc-1)*3); printf ("t:%d | consommer un objetn", tc-t0);
  consommer(c);// cosnommer d'un objet...
  
  if ((rand()%5) == 0){
   TextBackground (WHITE);
   TextColor (BLACK);
   GotoXY(70, 3+(nc-1)*3); printf ("                            ");
   break;
  }
 }
 time(&tc);
 cacher_cons(nc);
}// fin cosommateur...

void produire (t_case* c){//la production
 c->nb_rand = rand()%500; // un nombre aléatoire
 c->ch_rand = rand()%100+30; // un caractère aléatoire
}// fin production

void consommer (t_case c){//la consommation
 
}// fin consommation

void mettre(t_case c){// debut mettre
 semop(plein_mutex, &op_p, 1);
  if (mem2->plein == nb_cases){
   semop(plein_mutex, &op_v, 1);
   semop(file_prod, &op_p, 1);// bloquage...
   semop(plein_mutex, &op_p, 1);
  }
 semop(plein_mutex, &op_v, 1);
 
 semop(i_mutex, &op_p, 1);
  mem1[mem2->i].nb_rand = c.nb_rand;
  mem1[mem2->i].ch_rand = c.ch_rand;
  mem2->i = (mem2->i+1) % nb_cases;
  semop(plein_mutex, &op_p, 1);
   mem2->plein++;
   semop(file_cons, &op_v, 1);
  semop(plein_mutex, &op_v, 1);
  GotoXY (52 ,3+mem2->i*3);
  TextColor (RED);
  printf ("       n");
 semop(i_mutex, &op_v, 1);
}// fin mettre

void prendre(t_case *c){// debut prendre
 semop(plein_mutex, &op_p, 1);
  if (mem2->plein == 0){
   semop(plein_mutex, &op_v, 1);
   semop(file_cons, &op_p, 1);// bloquage...
   semop(plein_mutex, &op_p, 1);
  }
 semop(plein_mutex, &op_v, 1);

 semop(j_mutex, &op_p, 1);
  c->nb_rand = mem1[mem2->j].nb_rand;
  c->ch_rand = mem1[mem2->j].ch_rand;
  mem2->j = (mem2->j+1) % nb_cases;
  semop(plein_mutex, &op_p, 1);
   mem2->plein--;
   semop(file_prod, &op_v, 1);
  semop(plein_mutex, &op_v, 1);
 semop(j_mutex, &op_v, 1);
}// fin prendre

// les fonctions de dessins..
void tampon(int n){ //afficher le tampon...
 TextColor (BLUE);
 TextBackground(WHITE);
 int i;
 for (i=0; i<n; i++){
  GotoXY(51 ,2+i*3);
  printf ("_____________");
  GotoXY(50, 3+i*3);
  printf ("|             |");
  GotoXY(50, 4+i*3);
  printf ("|             |");
  GotoXY(50, 5+i*3);
  printf ("|             |");
  GotoXY(51, 5+i*3);
  printf ("_____________n");
 }
 GotoXY (54, 3+i*3);
 TextColor (RED);
 printf ("TAMPON");
}

void affiche_prod(int np){//afficher producteur
 GotoXY(5, 3+(np-1)*3);
 TextColor (WHITE);
 TextBackground(BLUE);
 printf ("  Prod %d  n", np);
}

void affiche_cons(int nc){//afficher consommateur
 GotoXY(100, 3+(nc-1)*3);
 TextColor (WHITE);
 TextBackground(RED);
 printf ("  Cons %d  n", nc); 
}

void cacher_prod(int np){
 GotoXY(5, 3+(np-1)*3);
 TextColor (WHITE);
 TextBackground(WHITE);
 printf ("           n", np);
}

void cacher_cons(int nc){
 GotoXY(100, 3+(nc-1)*3);
 TextColor (WHITE);
 TextBackground(WHITE);
 printf ("          n", nc);
}

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.