Problema de semáforos con memoria compartida (Productor-Consumidor)

Iniciado por hardcandy12, 8 Febrero 2012, 17:49 PM

0 Miembros y 1 Visitante están viendo este tema.

hardcandy12

Hola, tengo dificultades para resolver una modificación (especificada más abajo) de este problema en C para una máquina UNIX, y el problema es el siguiente:

Realizar un programa que implemente el problema del productor-consumidor con buffer circular utilizando semáforos y memoria compartida de la API System V. Para ello, utilizar como buffer una zona de memoria compartida (memoria principal) que contendrá N elementos (el tamaño del buffer será fijo y circular). Los procesos productor y consumidor se ejecutarán concurrentemente. Tener cuidado con la situación que se puede producir si termina la ejecución de un proceso antes de que comience a ejecutarse el otro ya que, en este caso, no existirá concurrencia e incluso puede dar algún error. Para solucionarlo hay distintas posibilidades. ¡Pensar en ello!

DATOS:
1.   El proceso productor se utilizará para generar las letras del abecedario y el proceso consumidor para mostrarlas en pantalla.
2.   El proceso productor debe generar 200 letras
3.   El tamaño del buffer debe ser de 15 elementos


Este problema lo tengo resuelto y funciona y el código es el siguiente:

//PROCESO PRODUCTOR

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#define SEMKEY 110
#define SHMKEY 75

#define EM  0  //Semaforo de Exclusion Mutua
#define EL  1  //Semáforo de Espacios Libres
#define ED  2  //Semaforo de Elementos Disponibles

int ed=0,el=0;
int semid;           
char caracter=65;
char carac[15];

struct sembuf sem_oper; // Para
union semun
{
               int val;
               struct semid_ds *semstat;
               unsigned short *array;
  }
arg;

void wait(int id)
{
      sem_oper.sem_num=id;  //actuamos sobre el semáforo id
      sem_oper.sem_op=-1;   //decremento
      sem_oper.sem_flg=SEM_UNDO; // Para evitar interbloqueos
      semop(semid, &sem_oper,1);
}

void signal(int id)
{
      sem_oper.sem_num=id;  //actuamos sobre el semáforo id
      sem_oper.sem_op=1;    //incremento
      sem_oper.sem_flg=SEM_UNDO; // Para evitar interbloqueos
      semop(semid, &sem_oper,1);
}

int main () {

      int n;
      int shmid[2];
      char *addr, *buf;
   
    // Crear la región de memoria y obtener la dirección
    if((shmid[0] = shmget (SHMKEY, sizeof(char)*15, 0777 | IPC_CREAT))==-1){
          printf("No se pudo reservar memoria");
          exit(-1);
      }

    // Enlazar región al espacio de direccionamiento del proceso
   
    addr = shmat (shmid[0], 0, 0);
    buf = addr;       //Reservar addr

    //crear 3 semáforos

      semid=semget(SEMKEY,3,0777|IPC_CREAT);

    // inicializar los semáforos
     
   arg.array=(unsigned short *) malloc(sizeof(short)*3);
        arg.array[0]=1;
        arg.array[1]=15;
        arg.array[2]=0;
        semctl (semid,3,SETALL,arg);
   
    // operamos sobre los semáforos
       for(n=1;n<=200;n++)
        {
            wait(EL);           //ver si hay espacios libres
            wait(EM);           // sección critica
                buf=addr;                    //Acceder a memoria compartida
                buf[el]=caracter;         //escribir el caracter en memoria
                el=(el+1)%15;              //actualizar el indice
                if(caracter=='Z')           
                    caracter='a';          //vuelve a empezar el abecedario   
                else if(caracter=='z')     //a z pase a A.
                    caracter='A';
                else
                    caracter++;
                signal(EM);    //salir de sc

            signal(ED);        //actualizar los elementos disponibles
        }
     
        free(arg.array);

    // Separar la región del espacio de direccionamiento del proceso
       
      shmdt (addr);
      for(n=0;n<2;n++)
      shmctl(shmid[n],IPC_RMID,0);
      free(arg.array);
      return 0;

} // fin del main

//PROCESO CONSUMIDOR

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

#define SEMKEY 110
#define SHMKEY 75

#define EM  0  //Semaforo de Exclusion Mutua
#define EL  1  //Semáforo de Espacios Libres
#define ED  2  //Semaforo de Elementos Disponibles

int ed=0;
int semid;         
char caracter=200;
char carac[15];

struct sembuf sem_oper;
union semun
{
               int val;
               struct semid_ds *semstat;
               unsigned short *array;
}
arg;

void wait(int id)
{
      sem_oper.sem_num=id;  //actuar sobre el semáforo correspondiente
      sem_oper.sem_op=-1;   //decremento 1 el semáforo
      sem_oper.sem_flg=SEM_UNDO; // Para evitar interbloqueos si un proceso acaba inesperadamente
      semop(semid, &sem_oper,1);
}

void signal(int id)
{
      sem_oper.sem_num=id;  //actuar sobre el semáforo correspondiente
      sem_oper.sem_op=1;    //incremento
      sem_oper.sem_flg=SEM_UNDO; // Para evitar interbloqueos
      semop(semid, &sem_oper,1);
}

int main () {

      int eof;
      int n;
      int shmid[2];
      char *addr, *buf;
     
    //Crear la región de memoria y obtener la dirección

    if((shmid[0] = shmget (SHMKEY, sizeof(char)*15, 0777 | IPC_CREAT))==-1){
          printf("No se pudo reservar memoria");
          exit(-1);
      }

    //Enlazar región al espacio de direccionamiento del proceso

    addr = shmat (shmid[0], 0, 0);   
    if((shmid[1] = shmget (SHMKEY, sizeof(int), 0777 | IPC_CREAT))==-1){
          printf("No se pudo reservar memoria");
          exit(-1);
      }

    // Enlazar región al espacio de direccionamiento del proceso

    eof = shmat (shmid[1], 0, 0);

    //creación de 3 semáforos

      semid=semget(SEMKEY,3,0777|IPC_CREAT);
   
    // inicialización de los semáforos

      arg.array=(unsigned short *) malloc(sizeof(short)*3);
      arg.array[0]=1;
      arg.array[1]=15;
      arg.array[2]=0;
      semctl (semid,3,SETALL,arg);

      // operamos sobre los semáforos

        for(n=1;n<=200;n++)          // 200 caracteres
        {
            wait(ED);                 //Comprobar que hay elementos disponibles
            wait(EM);                 // sección critica
            buf=addr;                   //acceder a memoria compartida
            caracter=buf[ed];           //leer el caracter   
            printf("%c",caracter);   //imprimir  por pantalla
            ed=(ed+1)%15;             //actualizar el indice
            signal(EM);               //salir de sección critica
            signal(EL);              //actualizar los espacios libres
        }

        semctl (semid,3,IPC_RMID,0);
       
   // Separar la región del espacio de direccionamiento del proceso
       
   shmdt (addr);
        shmdt (eof);
        for(n=0;n<2;n++)
        shmctl(shmid[n],IPC_RMID,0);
        free(arg.array);

      return 0;

} // fin del main

Ahora tengo que hacer una modificación y tengo dificultades para hacerlo, y el problema es el siguiente:

Modificar el ejercicio básico anterior para que el proceso productor en lugar de generar letras del abecedario, pida por teclado el nombre de un archivo (cuyo contenido sea texto en ASCII) e introduzca su contenido en el buffer y el proceso consumidor lo mostrará en pantalla. Se debe seguir respectando el tamaño del buffer.


Ayudenme a resolverlo por favor, un saludo.

Akai

Aquí no realizamos tareas, ejercicios etc etc etc...

En cambio, si lo intentas y tienes dudas, si te podemos ayudar, pero hacerlo por ti: NO

hardcandy12

Cita de: Akai en  8 Febrero 2012, 19:31 PM
Aquí no realizamos tareas, ejercicios etc etc etc...

En cambio, si lo intentas y tienes dudas, si te podemos ayudar, pero hacerlo por ti: NO

Lo he intentado y claro que tengo dudas y problemas a la hora de resolverlo, o esk no has leido lo que escribi arriba, y he pedido que me ayuden a resolverlo, no a que me lo hagan, puesto que la gran parte del ejercicio la he resuelto yo y solo tengo problemas con una modificacion del ejercicio, asike si me kieres ayudar lo dices y si no, no tienes porke decir lo que tengo que hacer yo o lo que tiene que hacer la gente.

Eternal Idol

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón