Implement the producer-consumer in such a way that the parent creates a shared m
ID: 3707488 • Letter: I
Question
Implement the producer-consumer in such a way that the parent creates a shared memory segment using posix API (memory mapped file) and creates a producer thread with one routine to run, and a consumer child with another routine to run. Pass the name of the shared memory file as an argument to each thread. Does this solution require a mutex or semaphore, or does the file implementation take care of mutual exclusion? By modify the following files.
producer.c
/**
* Simple program demonstrating shared memory in POSIX systems.
*
* This is the producer process that writes to the shared memory region.
*
* Figure 3.17
*
* @author Silberschatz, Galvin, and Gagne
* Operating System Concepts - Ninth Edition
* Copyright John Wiley & Sons - 2013
*
* modifications by dheller@cse.psu.edu, 31 Jan. 2014
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <errno.h>
void display(char *prog, char *bytes, int n);
int main(void)
{
const char *name = "/shm-example"; // file name
const int SIZE = 4096; // file size
const char *message0 = "Studying ";
const char *message1 = "Operating Systems ";
const char *message2 = "Is Fun!";
const char *msg_end = " ";
int shm_fd; // file descriptor, from shm_open()
char *shm_base; // base address, from mmap()
char *ptr; // shm_base is fixed, ptr is movable
/* create the shared memory segment as if it was a file */
shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);
if (shm_fd == -1) {
printf("prod: Shared memory failed: %s ", strerror(errno));
exit(1);
}
/* configure the size of the shared memory segment */
ftruncate(shm_fd, SIZE);
/* map the shared memory segment to the address space of the process */
shm_base = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm_base == MAP_FAILED) {
printf("prod: Map failed: %s ", strerror(errno));
// close and shm_unlink?
exit(1);
}
/**
* Write to the mapped shared memory region.
*
* We increment the value of ptr after each write, but we
* are ignoring the possibility that sprintf() fails.
*/
display("prod", shm_base, 64);
ptr = shm_base;
ptr += sprintf(ptr, "%s", message0);
ptr += sprintf(ptr, "%s", message1);
ptr += sprintf(ptr, "%s", message2);
ptr += sprintf(ptr, "%s", msg_end);
display("prod", shm_base, 64);
/* remove the mapped memory segment from the address space of the process */
if (munmap(shm_base, SIZE) == -1) {
printf("prod: Unmap failed: %s ", strerror(errno));
exit(1);
}
/* close the shared memory segment as if it was a file */
if (close(shm_fd) == -1) {
printf("prod: Close failed: %s ", strerror(errno));
exit(1);
}
return 0;
}
void display(char *prog, char *bytes, int n)
{
printf("display: %s ", prog);
for (int i = 0; i < n; i++)
{ printf("%02x%c", bytes[i], ((i+1)%16) ? ' ' : ' '); }
printf(" ");
}
consumer.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
void display(char *prog, char *bytes, int n);
int main(void)
{
const char *name = "/shm-example"; // file name
const int SIZE = 4096; // file size
int shm_fd; // file descriptor, from shm_open()
char *shm_base; // base address, from mmap()
/* open the shared memory segment as if it was a file */
shm_fd = shm_open(name, O_RDONLY, 0666);
if (shm_fd == -1) {
printf("cons: Shared memory failed: %s ", strerror(errno));
exit(1);
}
/* map the shared memory segment to the address space of the process */
shm_base = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
if (shm_base == MAP_FAILED) {
printf("cons: Map failed: %s ", strerror(errno));
// close and unlink?
exit(1);
}
/* read from the mapped shared memory segment */
display("cons", shm_base, 64); // first as bytes, then as a string
printf("%s", shm_base);
/* remove the mapped shared memory segment from the address space of the process */
if (munmap(shm_base, SIZE) == -1) {
printf("cons: Unmap failed: %s ", strerror(errno));
exit(1);
}
/* close the shared memory segment as if it was a file */
if (close(shm_fd) == -1) {
printf("cons: Close failed: %s ", strerror(errno));
exit(1);
}
/* remove the shared memory segment from the file system */
if (shm_unlink(name) == -1) {
printf("cons: Error removing %s: %s ", name, strerror(errno));
exit(1);
}
return 0;
}
void display(char *prog, char *bytes, int n)
{
printf("display: %s ", prog);
for (int i = 0; i < n; i++)
{ printf("%02x%c", bytes[i], ((i+1)%16) ? ' ' : ' '); }
printf(" ");
}
Explanation / Answer
CODE:
#include<sys/sem.h>
#include<semaphore.h>
#define MEMORY_KEY 5
#define SIZE_OF_ARRAY 10
struct wrapper
{
int array[SIZE_OF_ARRAY];
sem_t empty;
sem_t mutex;
sem_t full;
};
int memoryID;
struct wrapper *memory;
int rc;
void atexit_function() {
rc = shmctl(memoryID, IPC_RMID, NULL);
rc = shmdt(memory);
}
int main(int argc, char **argv)
{
int i;
atexit(atexit_function);
srand(time(NULL));
key_t sharedMemoryKey = ftok(".", MEMORY_KEY);
if (sharedMemoryKey == -1) {
perror("ftok():");
exit(1);
}
memoryID = shmget(sharedMemoryKey, sizeof(struct wrapper), IPC_CREAT | 0600);
if (memoryID == -1) {
perror("shmget():");
exit(1);
}
memory = shmat(memoryID, NULL, 0);
if (memory == (void *) -1) {
perror("shmat():");
exit(1);
}
for(i=0;i<SIZE_OF_ARRAY;i++)
{
memory->array[i] = 0;
}
sem_init(&memory->mutex, 1, 1);
sem_init(&memory->empty, 1, SIZE_OF_ARRAY);
sem_init(&memory->full, 1, 0);
if (memoryID == -1) {
perror("shmget(): ");
exit(1);
}
while(1)
{
int r = rand();
sem_wait(&memory->empty);
sem_wait(&memory->mutex);
int n;
sem_getvalue(&memory->full,&n);
printf("Adding task Value:%d Number of tasks waiting:%d ",r,n);
(memory->array)[n]=r;
usleep(1000000);
sem_post(&memory->mutex);
sem_post(&memory->full);
}
return 0;
}
cons.c
#define MEMORY_KEY 5
#define SIZE_OF_ARRAY 10
struct wrapper
{
int array[SIZE_OF_ARRAY];
sem_t empty;
sem_t mutex;
sem_t full;
};
int memoryID;
struct wrapper *memory;
int main(int argc, char **argv)
{
srand(time(NULL));
key_t sharedMemoryKey = ftok(".",MEMORY_KEY);
if(sharedMemoryKey==-1)
{
perror("ftok():");
exit(1);
}
memoryID=shmget(sharedMemoryKey,sizeof(struct wrapper),0);
if(memoryID==-1)
{
perror("shmget(): ");
exit(1);
}
memory = shmat(memoryID,NULL,0);
if(memory== (void*)-1)
{
perror("shmat():");
exit(1);
}
while(1)
{
int r = rand();
sem_wait(&memory->full);
sem_wait(&memory->mutex);
int n;
sem_getvalue(&memory->full,&n);
printf("Removed item: %d ",(memory->array)[n]);
usleep(1000000);
sem_post(&memory->mutex);
sem_post(&memory->empty);
}
return 0;
}