Práctica de Sistemas Operativos

Problema del Productor_Consumidor

El objetivo de esta práctica es dar solución al problema de acceso concurrente, que aparece entre un proceso productor, que genera información, y otro consumidor, que la aprovecha. En nuestro caso, el productor genera números aleatorios y el consumidor calcula la media de dichos números.

El intercambio de información entre ambos procesos se realiza mediante un array, incluido en un espacio de memoria compartida. Las funciones de manejo de memoria compartida se encuentran en rshmem.c y rshmem.h.

Utilizamos tres semáforos para la implementación, que controlan cada proceso hasta que el recurso está disponible. Los tres semáforos que empleamos son:

Las funciones de manejo de semáforos se encuentran en semafo.c.

El semáforo Mutex controla la entrada y salida de la Sección Crítica, compuesta por: el buffer limitado, los apuntadores de entrada y salida al mismo y el contador del número de elementos.

ppal.c

Otra versión del programa sería incluir en la Sección Crítica sólo el buffer limitado, que es lo que realmente van a compartir el proceso productor y el proceso consumidor. En tal caso los semáforos actúan como contadores.

seccrit.c


Autoras:



ppal.c

#include "rshmem.h"
#include <sys/sem.h>
#include <stdlib.h>
#define N 20

double main() {
   key_t claveMutex,claveLleno,claveVacio;  /* cualificadores semáforos */
   int Mutex,Lleno,Vacio;          /* semáforos */
   int *finProc =NULL;
   int *salida  =NULL;
   int *entrada =NULL;
   int *contador=NULL;
   int *array   =NULL;             /* almacén de elementos */
   int elemento;                   /* elemento producido-consumido */
   int total=0;                    /* suma producidos */
   int total1=0;                   /* suma consumidos */
   double mediaprod=0;             /* media producidos */
   double mediacon=0;              /* media consumidos */


   /* obtener una clave cualquiera para el recurso ipc */
      if ((key_t) -1 == (claveMutex = ftok("ppal", 's')) ||
       (key_t) -1 == (claveLleno = ftok("ppal", 'w')) ||
       (key_t) -1 == (claveVacio = ftok("ppal", 'j'))) {
      fprintf(stderr,"main: Error al crear la clave con ftok(3)\n");
      exit(1);
   }


   /* creamos los semáforos, asignando los valores iniciales */
   if (-1 ==(Mutex = semCreate(claveMutex,1))){
      fprintf(stderr,"main: No puede crear el semaforo\n");
      exit(1);
   }

   if (-1 ==(Lleno = semCreate(claveLleno,0))){
      fprintf(stderr,"main: No puede crear el semaforo\n");
      semClose(Mutex);
      exit(1);
   }

   if (-1 ==(Vacio = semCreate(claveVacio,N))){
      fprintf(stderr,"main: No puede crear el semaforo\n");
      semClose(Mutex);
      semClose(Lleno);
      exit(1);
   }


   /* creamos zona de memoria compartida */
   if (!crearMemoria()) {
      fprintf(stderr," error de crearMemoria\n");
      semClose(Mutex);
      semClose(Lleno);
      semClose(Vacio);
      exit(1);
   }

   /* variables de la sección crítica */
   contador = (int*) memoria;
   salida   = contador + sizeof(int) ; 
   entrada  = salida   + sizeof(int) ; 
   array    = entrada  + sizeof(int) ;
   finProc  = array    + sizeof(int)*N ;

   *contador = 0 ;
   *salida   = 0 ;
   *entrada  = 0 ;
   *finProc  = 0 ;

   if (0!=fork()) {  /* proceso padre, el productor */
      int i;
      int indprod=0;
         for (i=0; i< 1000; i++) {
         elemento = rand();/* producimos números aleatorios */
         semWait(Vacio);   /* mira si hay sitio */
         semWait(Mutex);   /* entrada s.c. */
                 
           array[*entrada]=elemento;
           *entrada=(*entrada+1)%N;
           *contador=*contador+1;

         semSignal(Mutex); /* salida s.c. */
         semSignal(Lleno); /* hay un elemento más */
         indprod+=1;
         total+=elemento;
         
      }
      mediaprod=total/indprod;
      printf("La media de los elementos producidos es: %lf\n",mediaprod);
      while (! *finProc) ;   /* espera al hijo */
      if(!eliminarMemoria()) /* eliminar la memoria compartida */
         fprintf(stderr,"error de eliminarMemoria\n");
      semClose(Mutex);
      semClose(Lleno);
      semClose(Vacio);
      exit(0);


   } else {    /* proceso hijo, consumidor */
      int i;
      int indcon=0;
     

      if (-1 == (Mutex = semOpen(claveMutex)))
         fprintf(stderr," No tengo el cualificador de Mutex\n");
      if (-1 == (Lleno = semOpen(claveLleno)))
         fprintf(stderr," No tengo el cualificador de Lleno\n");
      if (-1 == (Vacio = semOpen(claveVacio)))
         fprintf(stderr," No tengo el cualificador de Vacio\n");
 

      for (i=0; i< 1000; i++) {
         semWait(Lleno);     /* mira si hay algún elemento */
         semWait(Mutex);     /* entrada s.c. */

           elemento=array[*salida];
           *salida=(*salida+1)%N;
           *contador=*contador-1;
         
         semSignal(Mutex);   /* salida s.c. */
         semSignal(Vacio);   /* hay un elemento menos */
         indcon+=1;
         total1+=elemento;
      }
      mediacon=total1/indcon;
      printf("La media de los elementos consumidos es:%lf\n",mediacon);

      /* termina */
      semClose(Mutex);
      semClose(Lleno);
      semClose(Vacio);
      *finProc = 1;
      exit(0);
   }
  
}





seccrit.c
#include "rshmem.h"
#include <sys/sem.h>
#include <stdlib.h>
#define N 20

double factorial(int n){
   if(n<0) return(-1);
   if(n==0) return(1);
   return (n*factorial(n-1));
   }

double main() {
   key_t claveMutex;
   int Mutex;
   key_t claveLleno;
   int Lleno;
   key_t claveVacio;
   int Vacio; 
   int *finProc =NULL;
   int salida;
   int entrada;
   int *array   =NULL;
   int elemento;
   int total=0;
   int total1=0;
   double media=0;
   double mediaprod=0;


   if ((key_t) -1 == (claveMutex = ftok("ppal", 's')) ||
       (key_t) -1 == (claveLleno = ftok("ppal", 'w')) ||
       (key_t) -1 == (claveVacio = ftok("ppal", 'j'))) {
      fprintf(stderr,"main: Error al crear la clave con ftok(3)\n");
      exit(1);
   }

   if (-1 ==(Mutex = semCreate(claveMutex,1))){
      fprintf(stderr,"main: No puede crear el semaforo\n");
      exit(1);
   }

   if (-1 ==(Lleno = semCreate(claveLleno,0))){
      fprintf(stderr,"main: No puede crear el semaforo\n");
      semClose(Mutex);
      exit(1);
   }

   if (-1 ==(Vacio = semCreate(claveVacio,N))){
      fprintf(stderr,"main: No puede crear el semaforo\n");
      semClose(Mutex);
      semClose(Lleno);
      exit(1);
   }

   if (!crearMemoria()) {
      fprintf(stderr," error de crearMemoria\n");
      semClose(Mutex);
      semClose(Lleno);
      semClose(Vacio);
      exit(1);
   }

   array    = (int*) memoria;
   finProc  = array    + sizeof(int)*N ;

   salida   = 0 ;
   entrada  = 0 ;
   *finProc  = 0 ;

   if (0!=fork()) {
      int i;
      int indprod;
         for (i=0; i< 1000; i++) {
         elemento = rand();/*producir*/
         semWait(Vacio);
         semWait(Mutex);
                 
           array[entrada]=elemento;
        
         semSignal(Mutex);
         semSignal(Lleno);
         entrada=(entrada+1)%N;
         indprod+=1;
         total+=elemento;
      }

      mediaprod=total/indprod;
      printf("La media elementos producidos es:%lf\n",mediaprod);
      
      while (! *finProc) ;
      if(!eliminarMemoria())
         fprintf(stderr,"error de eliminarMemoria\n");
      semClose(Mutex);
      semClose(Lleno);
      semClose(Vacio);
      exit(0);
   } else {  
      int i;
      int indice=0;
     

      if (-1 == (Mutex = semOpen(claveMutex)))
         fprintf(stderr," No tengo el cualificador de Mutex\n");
      if (-1 == (Lleno = semOpen(claveLleno)))
         fprintf(stderr," No tengo el cualificador de Lleno\n");
      if (-1 == (Vacio = semOpen(claveVacio)))
         fprintf(stderr," No tengo el cualificador de Vacio\n");
 

      for (i=0; i< 1000; i++) {
         semWait(Lleno);
         semWait(Mutex);

           elemento=array[salida];
         
         semSignal(Mutex);
         semSignal(Vacio);
         salida=(salida+1)%N;

         
         indice+=1;
         total1+=elemento;
      }
      media=total1/indice;
      printf("La media de los elementos consumidos es:%lf\n",media);

      semClose(Mutex);
      semClose(Lleno);
      semClose(Vacio);
      *finProc = 1;
      exit(0);
   }
  
}