Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Implement the producer-consumer in such a way that the parent creates a shared m

ID: 3707494 • 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? Can the producer and consumer threads write to the file at the same time? By modifying following files and combine them into one.

producer.c

#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

PROGRAM:

#include<sys/types.h>

#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

#include<sys/sem.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 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;

}