Question: I need help with my assignment. I got the consumer code done but I need help with the producer code where it starts at void

I need help with my assignment. I got the consumer code done but I need help with the producer code where it starts at void Producer. I know I'm not getting that right. If anyone can help figure that part out because that is all I can't get right. You are welcome to look at the consumer code but I feel that is correct. Below is the assignment instrunctons and the code for procducer.c and consumer.c

In this assignment, you will write producer and consumer programs that communicate through a bounded buffer in shared memory. The code that you will need to write will be based on the code given in class for forking a child process, creating a shared memory block and implementing a bounded buffer accessed by a producer and a consumer. Write your code in the given producer.c and consumer.c source files, and follow the instructions provided in these files. Note that the low-level functions for reading from and writing to the shared memory block are already provided to you. Please use the provided functions; do not write your own implementation of an already provided function.

As you can see in the given producer.c source file, the producer process is the parent process that creates (forks) a child process and loads the consumer executable into it. The consumer executable will be generated by compiling consumer.c (after you write the required code in it). After writing all the required code in both consumer.c and producer.c, use the following commands to compile the two programs and build the two executables:

gcc producer.c -lrt -o producer

gcc consumer.c -lrt -o consumer

The producer program (parent) takes the following three command-line arguments (all integers):

The size of the bounded buffer (bufSize). This is the number of items that can fit in the bounded buffer.

The number of items to produce/consume (itemCnt). Typically, itemCnt will be much larger than bufSize.

A seed for the random number generator (randSeed). This will allow us to test the program using different data.

The producer program creates a shared memory block with a fixed size of 4K (its name is OS_HW1). The producer then uses this block to communicate with the consumer. The block consists of a header followed by the bounded buffer with the given bufSize. The header contains the following four integers in order:

bufSize

itemCnt

in: the index of the next item to be produced

out: the index of the next item to be consumed

The main in the producer program first calls the function InitShm() to create the shared memory block and initialize its header with the above four integer values. It then forks a child process and loads the consumer executable into it. The parent process calls the function Producer() to actually generate the items and write them into the bounded buffer. The producer must generate itemCnt random integers in the range 0 to 100. Simply call the provided GetRand() function to do that. The main point is that when the bounded buffer is full, the producer must wait until the consumer has consumed at least one item.

The consumer program, in turn, performs the following main steps:

Opening and mapping the shared memory block created by the producer (its name is OS_HW1).

Reading the four integer values from the header.

Reading all the items written by the producer (their count is itemCnt). The main point is that when the bounded buffer is empty, the consumer must wait until the producer has produced at least one more item.

The producer/consumer code that you will need to write will be very similar to the bounded-buffer producer/consumer pseudo-code given in class, but make sure that you do the following:

Whenever you read any of the shared variables (in and out), you should read the latest value from the shared buffer using the provided GetIn() and GetOut() functions.

Whenever you update any of the shared variables (in and out), you should update their values in the shared buffer using the provided SetIn() and SetOut() functions.

Reading from and writing into the shared buffer should be done using the provided ReadAtBufIndex() and WriteAtBufIndex() functions.

Use the provided GetRand() function to generate a random number in the range 0 to 100.

Producer code

#include #include #include #include #include #include #include #include #include

// Size of shared memory block // Pass this to ftruncate and mmap #define SHM_SIZE 4096

// Global pointer to the shared memory block // This should receive the return value of mmap // Don't change this pointer in any function void* gShmPtr;

// You won't necessarily need all the functions below void Producer(int, int, int); void InitShm(int, int); void SetBufSize(int); void SetItemCnt(int); void SetIn(int); void SetOut(int); void SetHeaderVal(int, int); int GetBufSize(); int GetItemCnt(); int GetIn(); int GetOut(); int GetHeaderVal(int); void WriteAtBufIndex(int, int); int ReadAtBufIndex(int); int GetRand(int, int);

int main(int argc, char* argv[]) { pid_t pid; int bufSize; // Bounded buffer size int itemCnt; // Number of items to be produced int randSeed; // Seed for the random number generator

if(argc != 4){ printf("Invalid number of command-line arguments "); exit(1); } bufSize = atoi(argv[1]); itemCnt = atoi(argv[2]); randSeed = atoi(argv[3]);

// Function that creates a shared memory segment and initializes its header InitShm(bufSize, itemCnt);

/* fork a child process */ pid = fork();

if (pid < 0) { /* error occurred */ fprintf(stderr, "Fork Failed "); exit(1); } else if (pid == 0) { /* child process */ printf("Launching Consumer "); execlp("./consumer","consumer",NULL); } else { /* parent process */ /* parent will wait for the child to complete */ printf("Starting Producer "); // The function that actually implements the production Producer(bufSize, itemCnt, randSeed); printf("Producer done and waiting for consumer "); wait(NULL); printf("Consumer Completed "); } return 0; }

void InitShm(int bufSize, int itemCnt) { int in = 0; int out = 0; const char *name = "OS_HW1"; // Name of shared memory object to be passed to shm_open

//shared memory file decriptor int shm_fd;

//create the shared memory object shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);

//configure the size of the shared memory object ftruncate(shm_fd,4096);

//memory map the shared memory object gShmPtr = mmap(0, 4096, PROT_WRITE | PROT_READ, MAP_SHARED, shm_fd, 0);

// Write code here to create a shared memory block and map it to gShmPtr // Use the above name. // **Extremely Important: map the shared memory block for both reading and writing // Use PROT_READ | PROT_WRITE // Write code here to set the values of the four integers in the header // Just call the functions provided below, like this SetBufSize(bufSize); SetItemCnt(itemCnt); SetIn(in); SetOut(out); }

void Producer(int bufSize, int itemCnt, int randSeed) { int in = 0; int out = 0; int i; int val;

srand(randSeed);

for (i = 1; i <= 10; i++) { itemCnt = rand() % 100 + 1; /* produce an item in next produced */ while (((GetIn() + 1) % bufSize) == GetOut()); val = WriteAtBufIndex(i, ) GetRand(itemCnt, val); SetIn((SetIn(in) + 1) % bufSize); SetIn(in); printf("Producing Item %d with value %d at Index %d ", i, val, in); }

// Write code here to produce itemCnt integer values in the range [0-100] // Use the functions provided below to get/set the values of shared variables "in" and "out" // Use the provided function WriteAtBufIndex() to write into the bounded buffer // Use the provided function GetRand() to generate a random number in the specified range // **Extremely Important: Remember to set the value of any shared variable you change locally // Use the following print statement to report the production of an item: // printf("Producing Item %d with value %d at Index %d ", i, val, in); // where i is the item number, val is the item value, in is its index in the bounded buffer printf("Producer Completed "); }

// Set the value of shared variable "bufSize" void SetBufSize(int val) { SetHeaderVal(0, val); }

// Set the value of shared variable "itemCnt" void SetItemCnt(int val) { SetHeaderVal(1, val); }

// Set the value of shared variable "in" void SetIn(int val) { SetHeaderVal(2, val); }

// Set the value of shared variable "out" void SetOut(int val) { SetHeaderVal(3, val); }

// Set the value of the ith value in the header void SetHeaderVal(int i, int val) { void* ptr = gShmPtr + i*sizeof(int); memcpy(ptr, &val, sizeof(int)); }

// Get the value of shared variable "bufSize" int GetBufSize() { return GetHeaderVal(0); }

// Get the value of shared variable "itemCnt" int GetItemCnt() { return GetHeaderVal(1); }

// Get the value of shared variable "in" int GetIn() { return GetHeaderVal(2); }

// Get the value of shared variable "out" int GetOut() { return GetHeaderVal(3); }

// Get the ith value in the header int GetHeaderVal(int i) { int val; void* ptr = gShmPtr + i*sizeof(int); memcpy(&val, ptr, sizeof(int)); return val; }

// Write the given val at the given index in the bounded buffer void WriteAtBufIndex(int indx, int val) { // Skip the four-integer header and go to the given index void* ptr = gShmPtr + 4*sizeof(int) + indx*sizeof(int); memcpy(ptr, &val, sizeof(int)); }

// Read the val at the given index in the bounded buffer int ReadAtBufIndex(int indx) { int val;

// Skip the four-integer header and go to the given index void* ptr = gShmPtr + 4*sizeof(int) + indx*sizeof(int); memcpy(&val, ptr, sizeof(int)); return val; }

// Get a random number in the range [x, y] int GetRand(int x, int y) { int r = rand(); r = x + r % (y-x+1); return r; }

Consumer Code

#include #include #include #include #include #include #include

// Size of shared memory block // Pass this to ftruncate and mmap #define SHM_SIZE 4096

// Global pointer to the shared memory block // This should receive the return value of mmap // Don't change this pointer in any function void* gShmPtr;

// You won't necessarily need all the functions below void SetIn(int); void SetOut(int); void SetHeaderVal(int, int); int GetBufSize(); int GetItemCnt(); int GetIn(); int GetOut(); int GetHeaderVal(int); void WriteAtBufIndex(int, int); int ReadAtBufIndex(int);

int main() { const char *name = "OS_HW1"; // Name of shared memory block to be passed to shm_open int bufSize; // Bounded buffer size int itemCnt; // Number of items to be consumed int in; // Index of next item to produce int out; // Index of next item to consume

//shared memory file descriptor int shm_fd;

//open the shared memory object shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666);

//configure the size of the shared memory object ftruncate(shm_fd,4096);

//memory map the shared memory object gShmPtr = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);

// Write code here to create a shared memory block and map it to gShmPtr // Use the above name // **Extremely Important: map the shared memory block for both reading and writing // Use PROT_READ | PROT_WRITE

// Write code here to read the four integers from the header of the shared memory block // These are: bufSize, itemCnt, in, out // Just call the functions provided below like this: bufSize = GetBufSize(); itemCnt = GetItemCnt(); in = GetIn(); out = GetOut(); // Write code here to check that the consumer has read the right values: printf("Consumer reading: bufSize = %d ",bufSize); printf("Consumer reading: itemCnt = %d ",itemCnt);

int i = 1; int val; for(i; i <= itemCnt; i++){ while (GetIn() == GetOut()); val = ReadAtBufIndex(GetOut()); printf("Consuming Item %d with value %d at Index %d ", i, val, out); SetOut((GetOut() + 1) %bufSize); /* consume the item in next consumed */ }

// Write code here to consume all the items produced by the producer // Use the functions provided below to get/set the values of shared variables in, out, bufSize // Use the provided function ReadAtBufIndex() to read from the bounded buffer // **Extremely Important: Remember to set the value of any shared variable you change locally // Use the following print statement to report the consumption of an item: // printf("Consuming Item %d with value %d at Index %d ", i, val, out); // where i is the item number, val is the item value, out is its index in the bounded buffer // remove the shared memory segment if (shm_unlink(name) == -1) { printf("Error removing %s ",name); exit(-1); }

return 0; }

// Set the value of shared variable "in" void SetIn(int val) { SetHeaderVal(2, val); } // Set the value of shared variable "out" void SetOut(int val) { SetHeaderVal(3, val); } // Set the value of the ith value in the header void SetHeaderVal(int i, int val) { void* ptr = gShmPtr + i*sizeof(int); memcpy(ptr, &val, sizeof(int)); } // Get the value of shared variable "bufSize" int GetBufSize() { return GetHeaderVal(0); } // Get the value of shared variable "itemCnt" int GetItemCnt() { return GetHeaderVal(1); } // Get the value of shared variable "in" int GetIn() { return GetHeaderVal(2); } // Get the value of shared variable "out" int GetOut() { return GetHeaderVal(3); } // Get the ith value in the header int GetHeaderVal(int i) { int val; void* ptr = gShmPtr + i*sizeof(int); memcpy(&val, ptr, sizeof(int)); return val; }

// Write the given val at the given index in the bounded buffer void WriteAtBufIndex(int indx, int val) { // Skip the four-integer header and go to the given index void* ptr = gShmPtr + 4*sizeof(int) + indx*sizeof(int); memcpy(ptr, &val, sizeof(int)); }

// Read the val at the given index in the bounded buffer int ReadAtBufIndex(int indx) { int val; // Skip the four-integer header and go to the given index void* ptr = gShmPtr + 4*sizeof(int) + indx*sizeof(int); memcpy(&val, ptr, sizeof(int)); return val; } // Get a random number in the range [x, y] int GetRand(int x, int y) { int r = rand(); r = x + r % (y-x+1); return r; }

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!