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: 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;

}