|
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. |