How to get out of the problem of a simple producer-consumer

I am trying to develop 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 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 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 in a dead end. 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 time to say goodbye! consuming //deadlock - nothing written 

Please note: "Goodbye!" Not written. On the other hand, excess "consumption". What is wrong with this decision? Using a global variable to detect the end is not suitable? I can not understand this ...

Thanks for any ideas.

EDIT: In accordance with your advice, I changed the distribution of the local variable to volatile and added "\ n", but the problem persists.

+4
source share
2 answers

You should also share your flag, this works the way 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 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; } 
+3
source

volatile will not help you here because you are developing your processes. This will copy g_lastImage, and therefore the parent process that the producer () calls will change its own g_lastImage value, while the childprocess (which gets its own copy of this variable in fork) will always have g_lastImage == 0 and therefore you end up in dead end. You can simply insert the g_lastImage selection into the distribution of your semaphores, since it seems that you correctly assigned them to them in poth processes;)

+1
source

Source: https://habr.com/ru/post/1348047/


All Articles