I am working on a reader/writer program where there is one writer to n readers. I am having an issue where if multiple readers are in, like the screenshot posted below, then the entire message from shared memory isnt displayed.
Output:
Enter a Message: Test
Reader1: Test
Reader2: Test
Writer: test test
Reader1: test
Reader2: test test
Writer:
Readers:
I have tried to add a count variable because I assume that the writers turn is being flagged before all readers have the ability to print and its making the writer then exit the nested while() in the writer and stop the readers from printing.
Any suggestions on to make the readers both print, whether it be a flag or some sort of count? Attached below are also screenshots of the writer and reader loops.
Reader:
int main() {
DataShared data;
data.turn = 0;
signal(SIGINT, sigHandler);
//generates key
key = ftok("mkey",65);
//returns an identifier in mId
if ((mId = shmget(key, SIZE, IPC_CREAT|S_IRUSR|S_IWUSR)) < 0){
perror("shared memory error");
exit(1);
}
// shmat to attach to shared memory
if((mPtr = shmat(mId, 0, 0)) == (void*) -1) {
perror("Can't attach\n");
exit(1);
}
while(1) {
// request critical section
while(!data.turn && data.count == 0) {
//not time for the reader, check if token is changed.
memcpy(&data, mPtr, sizeof(DataShared));
}
data.count++;
// enter critical section
usleep(1);
fprintf(stderr, "Read from memory: %s\n", data.message);
usleep(1);
// leave critical section
data.count--;
while(data.count > 0){
;
}
data.turn = 0;
memcpy(mPtr, &data, sizeof(DataShared));
};
return 0;
}
Writer:
int main() {
DataShared data;
data.turn = 0;
data.count = 0;
signal(SIGINT, sigHandler);
key = ftok("mkey",65);
if((shmId = shmget(key, SIZE, IPC_CREAT|S_IRUSR|S_IWUSR)) < 0 ) {
perror("Error creating shared memory\n");
exit(1);
}
if((shmPtr = shmat(shmId, 0, 0)) == (void*) -1) {
perror("Can't attach\n");
exit(1);
}
while(1) {
while (data.turn) {
memcpy(&data, shmPtr, sizeof(DataShared));
}
// enter critical section
printf("Enter a message: \n" );
fgets(data.message, 1024, stdin);
// leave critical section
printf("Message written to memory: %s\n", data.message);
data.turn = 1;
memcpy(shmPtr, &data, sizeof(DataShared));
};
return 0;
}
This may not be the explanation of your observation, but what you do is fishy.
You have multiple processes and the OS schedules each process.
First, there is no guarantee that all readers will read the message. It is very well possible that one reader finishes, sets the flag to 0 and copies the data back to shared memory before another reader had a chance to read the data.
Then your data.count
. It starts with the local variable data
of the writer. there you do not initialize data.count
so it has an indeterminate value. In the readers you set it to 0 but it will be overwritten with the value from shared memory (the indeterminate value). You do a ++, later a -- and then wait for it to become 0. How would that ever become zero? That reader could wait forever.