Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

WRITE CODE WHERE IT SAYS TO WRITE CODE: producer.c #include #include #include #include #include #include #include #include #include // Size of shared memory block //

WRITE CODE WHERE IT SAYS TO WRITE

image text in transcribed

image text in transcribed

CODE: producer.c

#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]); // Write code to check the validity of the command-line arguments

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

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

if (pid

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

// 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); }

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

// Write code here to produce itemCnt integer values in the range [10-2500] // 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); }

// 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; }

// Set the ith value in the header void SetHeaderVal(int i, int val) { // Write the implementation

}

// 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); }

// 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) { // Write the implementation }

// 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; }

CODE: consumer.c

#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_yourName"; // 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 // 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(); // Write code here to check that the consumer has read the right values: printf("Consumer reading: bufSize = %d ",bufSize);

// 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); }

// 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; }

// Set the ith value in the header void SetHeaderVal(int i, int val) { // Write the implementation

}

// 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); }

// Write the given val at the given index in the bounded buffer void WriteAtBufIndex(int indx, int val) { // Write the implementation

}

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

As you can see in the given producer_template.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 -Irt -o producer gcc consumer.c -Irt -o consumer The producer program (parent) takes the following three command-line arguments (all integers): 1. The size of the bounded buffer (bufSize). This is the number of items that can fit in the bounded buffer. This cannot exceed 512. Your program should check if the value of thiscommand line argument is within the valid range ( 2 to 512); if not, it should print an appropriate error message and terminate. 2. The number of items to produce/consume (itemCnt). Your program should work correctly for any itemCnt that is greater than 0 . However, in an interesting test case, itemCnt will be much larger than bufSize. If your program works only if itemCnt is less than bufSize, you won't get any credit, as you won't be solving the bounded-buffer problem. 3. 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. Let the name of the shared memory block be OS_HW1_yourName, where "yourName" should be your actual full name. The purpose of this is to avoid interfering with other students' work if you happen to be running your programs on the same shared server. 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: 1. bufSize 2. itemCnt 3. in: the index of the next item to be produced 4. 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 10 to 2500 . Simply call the provided GetRand() function to do that. The key 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: 1. Opening and mapping the shared memory block created by the producer. The shared memory block name must match the name of the block created by the producer: OS_HW1_yourName. 2. Reading the four integer values from the header. 3. Reading all the items written by the producer to the shared memory buffer (their count is itemCnt). The key 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: 1. Whenever you read any of the shared variables (in and out), you must read the latest value from the shared buffer using the provided GetIn() and GetOut() functions. 2. Whenever you update any of the shared variables (in and out), you must update their values in the shared buffer using the provided Setln() and SetOut() functions. 3. Reading from and writing into the shared buffer should be done using the provided ReadAtBuflndex() and WriteAtBuflndex() functions. 4. Use the provided GetRand() function to generate a random number in the above-specified ranqe

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image_2

Step: 3

blur-text-image_3

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

More Books

Students also viewed these Databases questions

Question

What does stickiest refer to in regard to social media

Answered: 1 week ago