How to quit simple Producer-Consumer problem
I am trying to work out a simple producer-consumer program. I have this code:
//global variable g_lastImage is declared as:
volatile int g_lastImage = 0;
void producer(void) {
int i = 0;
while (1) {
sem_wait(&g_shm->PSem);
printf("I:%d\n",i);
if (i == 5) {
g_lastImage = 1;
printf("It's time to say goodbye!\n");
sem_post(&g_shm->ChSem);
return;
}
printf("producing\n");
i++;
sem_post(&g_shm->ChSem);
}
}
void consumer(void) {
while (1) {
sem_wait(&g_shm->ChSem);
if (g_lastImage) {
printf("Bye!\n");
return;
}
printf("consuming\n");
sem_post(&g_shm->PSem);
}
}
int main() {
alloc(); /*allocates shared memory and two semaphores,
ChSem on initial counter value 0 and PSem on value 1*/
int processes = 1; //let's start with one process only just for now
int id = 0, i = 0, status;
for (i = 0; i < processes; i++) {
id = fork();
if (id < 0) {
perror ("error\n");
exit(1);
} else if (id == 0) {
consumer();
printf("child exits\n");
exit(0);
}
}
producer();
for (i = 0; i < processes; ++i) {
wait(&status);
}
return 1;
}
Unfortunately this code ends with deadlock. I have this output:
I:0
producing
consuming
I:1
producing
consuming
I:2
producing
consuming
I:3
producing
consuming
I:4
producing
consuming
I:5
It's time to say goodbye!
consuming
//deadlock - nothing written
Please notice that "Bye!" is not written. On the other hand extra "consuming" is. What is wrong with this solution? Using global variable开发者_运维问答 for detecting the end is not ok? Can't figure it out...
Thank you for any ideas.
EDIT: Acording to your advices I changed the allocation of local variable to volatile and added the '\n' but the problem persists.
You have to share your flag too, this works as you expect :
#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/mman.h>
struct Shared
{
sem_t PSem ;
sem_t ChSem ;
int g_lastImage ;
} * g_shm ;
void producer(void) {
int i = 0;
while (1) {
sem_wait(&g_shm->PSem);
printf("I:%d\n",i);
if (i == 5) {
g_shm->g_lastImage = 1;
printf("It's time to say goodbye!\n");
sem_post(&g_shm->ChSem);
return;
}
printf("producing\n");
i++;
sem_post(&g_shm->ChSem);
}
}
void consumer(void) {
while (1) {
sem_wait(&g_shm->ChSem);
if (g_shm->g_lastImage) {
printf("Bye!\n");
return;
}
printf("consuming\n");
sem_post(&g_shm->PSem);
}
}
int main()
{
g_shm = mmap( NULL , sizeof( struct Shared ) , PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANONYMOUS , -1 , 0 );
sem_init( & g_shm->PSem , 1 , 1 );
sem_init( & g_shm->ChSem , 1 , 0 );
g_shm->g_lastImage = 0 ;
int processes = 1;
int id = 0, i = 0, status;
for (i = 0; i < processes; i++)
{
id = fork();
if (id < 0) {
perror ("error\n");
exit(1);
} else if (id == 0) {
consumer();
printf("child exits\n");
exit(0);
}
}
producer();
for (i = 0; i < processes; ++i)
{
wait(&status);
}
return 1;
}
volatile won't help you here, because you fork your processes. This will result in a copy of g_lastImage and therefore the parentprocess, which calls producer() will change its own value of g_lastImage, whereas the childprocess (who gets its own copy of that variable at fork) will always have g_lastImage == 0 and therefore you end up in a deadlock. You might just insert the allocation of g_lastImage into the allocation of your semaphores as well, as it seems that you allocated them correctly to have them in poth processes ;)
精彩评论