4

私は単純な生産者/消費者プログラムを作成しようとしています。私はこのコードを持っています:

//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;
}

残念ながら、このコードはデッドロックで終了します。私はこの出力を持っています:

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」を追加しましたが、問題は解決しません。

4

2 に答える 2

3

あなたもあなたの旗を共有しなければなりません、これはあなたが期待するように働きます:

#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;
}
于 2011-04-14T08:21:56.573 に答える
1

プロセスをフォークするため、volatileはここでは役に立ちません。これにより、g_lastImageのコピーが作成されるため、producer()を呼び出すparentprocessはg_lastImageの独自の値を変更しますが、childprocess(forkでその変数の独自のコピーを取得する)は常にg_lastImage == 0であるため、あなたは行き​​詰まりに終わります。g_lastImageの割り当てをセマフォの割り当てに挿入するだけでもかまいません。これは、セマフォを正しく割り当てて、pothプロセスに含めるように見えるためです;)

于 2011-04-14T09:30:22.470 に答える