Producer/Consumer Problem

48 views 10:32 am 0 Comments March 28, 2023

 

5004CEM Lab 16

Producer/Consumer Problem

In this lab, you will create a program that recreates the consumer/producer problem.

You should adapt the code (prodcon_example2.c) provided in Session16 on the server or on AULA.

See the ‘Getting Started with Lab 16’ video on AULA to give you additional information on completing this lab.

If you have any additional questions on this lab or any other labs please do not hesitate to ask your tutor and/or email me on [email protected].

Introduction – Consumer/Producer

The producer/consumer example code (prodcon_example2) provided isn’t perfect.

It’s got a fixed-length buffer (which is OK),

and can only use it once (which is not).

Here are the requirements:

It should be possible to have an arbitrary buffer length

It should be possible to push an arbitrary amount of data through the shared buffer

The data should not be corrupted

That means: the consumer should not be able to read an empty buffer and the producer should not be able to write to a full one.

Basic Task – Consumer/Producer

Adapt the example code so it is possible to make use of different buffer lengths and allow the producer/consumer processes to loop back to the start of the buffer when reading and written to the buffer. The consumer and the producer will not be aware of where the other process is along the buffer, and so there is no way to prevent one writing/reading over the other.

Advanced Task – Producer/Consumer

Advanced Task a)

In the example code implement a ringbuffer that allows single characters to be written/read by the producer/consumer. As noted above the producer should not overwrite data not yet read by the consumer and the consumer should not read data in a slot where the producer has not added new data. This should make use of shared memory.

Advanced Task b)

Show the ringbuffer you created with shared memory works with different Buffer lengths. Explain what is happening.

Advanced Task c)

Show the ringbuffer you created with shared memory works with different speeds (sleep lengths) for the producer and consumer. Explain what is happening when you have the producer and consumer at different speeds.

.

Solution

#include <sys/ipc.h>

#include <sys/sem.h>

#include <sys/shm.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include “ops_sems.h”

#include <sys/wait.h>

int bufferlength=8; //Limited buffer length

int main(int argc, char argv[]){

int producerWaitTime, consumerWaitTime;

printf(“Choose buffer size: “);

scanf(“%d”, &bufferlength);

printf(“Choose producer wait time (2 default): “);

scanf(“%d”, &producerWaitTime);

printf(“Choose consumer wait time (1 default): “);

scanf(“%d”, &consumerWaitTime);

pid_t pid;

int status = 0;

int i;

// Set the index for the cell that is holding the position of the consumer

// Set the index for the cell that is holding the position of the producer

int poscon=bufferlength+1;

int posprod=bufferlength+2;

//Create shared memory segment

int shm_id=shmget(ftok(“prodcon_example2.c”,2),bufferlength,

0666|IPC_CREAT); //Use our source file as the “key”

int id=ops_semget(“prodcon_example2.c”,0);

char* data; //For our pointer to shared memory…

pid=fork();

if(pid){

//P1 – CONSUMER

shm_id=shmget(ftok(“prodcon_example2.c”,2),0,006);

//Attach the shared buffer

data = shmat(shm_id, (void *)0, 0);

//Allocate cell in shared memory to store position of consumer

//Allocate cell in shared memory to store position of producer

data[poscon]=0;

data[posprod]=0;

while(1){

ops_wait(id);

//Stops Consumer Reading data from the shared memory

while(data[poscon]==data[posprod]) {/*Wait Until not True*/}

// print where consumer is on the shared memory

printf(“Consuming item number %d…n”,data[poscon]);

sleep(consumerWaitTime);

char item=data[data[poscon]];

// print where the consumer is and the value being read

printf(“Consumed item number %d. Item value was %dn”, data[poscon],item);

// Move on the consumer on

data[poscon]=(data[poscon]+1)%bufferlength;

}

//Detatch

shmdt(data);

printf(“All done consuming.n”);

wait(&status); //For child process so that we can

//Delete the shared memory

printf(“Child ended, removing shmn”);

shmctl(shm_id, IPC_RMID, NULL);

}

else{

//P2 – PRODUCER

shm_id=shmget(ftok(“prodcon_example2.c”,2),0,006);

//Attach the shared buffer

data = shmat(shm_id, (void *)0, 0);

data[poscon]=0;

data[posprod]=0;

while(1){

while( (data[posprod]+1)==data[poscon]);

printf(“Producing item number %d…n”,data[posprod]);

sleep(producerWaitTime);

data[data[posprod]]=data[posprod]*2; //Simple data, easy to check.

printf(“Produced item number %d. Value is %dn”, data[posprod],data[data[posprod]]);

ops_signal(id);

data[posprod]=(data[posprod]+1)%bufferlength;

}

//Detatch

shmdt(data);

printf(“Producer finished.”);

}

}

Lab Evidence

The commented code and examples of it running to show that the ringbuffer works when the buffer length is changed, and the speeds of the producer and consumer are different.