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.
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.