#c #posix #parallel-processing #producer-consumer
#c #posix #параллельная обработка #производитель-потребитель
Вопрос:
Я пытаюсь разработать простую программу производителя-потребителя. У меня есть этот код:
//global variable g_lastImage is declared as:
volatile int g_lastImage = 0;
void producer(void) {
int i = 0;
while (1) {
sem_wait(amp;g_shm->PSem);
printf("I:%dn",i);
if (i == 5) {
g_lastImage = 1;
printf("It's time to say goodbye!n");
sem_post(amp;g_shm->ChSem);
return;
}
printf("producingn");
i ;
sem_post(amp;g_shm->ChSem);
}
}
void consumer(void) {
while (1) {
sem_wait(amp;g_shm->ChSem);
if (g_lastImage) {
printf("Bye!n");
return;
}
printf("consumingn");
sem_post(amp;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 ("errorn");
exit(1);
} else if (id == 0) {
consumer();
printf("child exitsn");
exit(0);
}
}
producer();
for (i = 0; i < processes; i) {
wait(amp;status);
}
return 1;
}
К сожалению, этот код заканчивается взаимоблокировкой. У меня есть этот вывод:
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
Пожалуйста, обратите внимание, что «Пока!» не написано. С другой стороны, дополнительное «потребление» есть. Что не так с этим решением? Использование глобальной переменной для определения конца не подходит? Не могу разобраться…
Спасибо за любые идеи.
РЕДАКТИРОВАТЬ: В соответствии с вашими советами я изменил выделение локальной переменной на volatile и добавил ‘ n’, но проблема сохраняется.
Комментарии:
1. Извините за эту глупую ошибку, эта напечатана, хотя проблема сохраняется.
Ответ №1:
Вы также должны поделиться своим флагом, это работает так, как вы ожидаете :
#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(amp;g_shm->PSem);
printf("I:%dn",i);
if (i == 5) {
g_shm->g_lastImage = 1;
printf("It's time to say goodbye!n");
sem_post(amp;g_shm->ChSem);
return;
}
printf("producingn");
i ;
sem_post(amp;g_shm->ChSem);
}
}
void consumer(void) {
while (1) {
sem_wait(amp;g_shm->ChSem);
if (g_shm->g_lastImage) {
printf("Bye!n");
return;
}
printf("consumingn");
sem_post(amp;g_shm->PSem);
}
}
int main()
{
g_shm = mmap( NULL , sizeof( struct Shared ) , PROT_READ | PROT_WRITE , MAP_SHARED | MAP_ANONYMOUS , -1 , 0 );
sem_init( amp; g_shm->PSem , 1 , 1 );
sem_init( amp; 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 ("errorn");
exit(1);
} else if (id == 0) {
consumer();
printf("child exitsn");
exit(0);
}
}
producer();
for (i = 0; i < processes; i)
{
wait(amp;status);
}
return 1;
}
Комментарии:
1. Если бы я мог поставить сотню плюсов, я бы определенно поставил! Спасибо
Ответ №2:
volatile вам здесь не поможет, потому что вы разветвляете свои процессы. Это приведет к созданию копии g_lastImage и, следовательно, родительский процесс, который вызывает producer(), изменит свое собственное значение g_lastImage, тогда как дочерний процесс (который получает свою собственную копию этой переменной при fork) всегда будет иметь g_lastImage == 0, и, следовательно, вы окажетесь в тупике. Вы могли бы просто вставить выделение g_lastImage также в выделение ваших семафоров, поскольку кажется, что вы распределили их правильно, чтобы они были в других процессах 😉
Комментарии:
1. кстати, чтобы позволить ему работать с большим количеством процессов, мне придется публиковать ChSem столько раз, сколько у меня есть процессов, верно?