2011-04-14 115 views
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 

请注意“再见!”不写。另一方面额外的“消费”是。这个解决方案有什么问题?使用全局变量来检测结束是不行的?想不出来...

谢谢你的任何想法。

编辑: Acording你的建议我改变局部变量的分配挥发性,并且增加了“\ n”,但问题仍然存在。

+0

对不起,愚蠢的错误,这个打印出来,虽然问题依然存在。 – tsusanka 2011-04-14 08:11:28

回答

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; 
} 
+0

如果我可以给一百个加号,我肯定会!谢谢 – tsusanka 2011-04-14 09:45:28

1

挥发性不会帮助你在这里,因为你叉你的流程。这将导致g_lastImage的副本,因此调用producer()的父进程将更改自己的g_lastImage值,而子进程(在fork中获取自己的该副本的副本)始终具有g_lastImage == 0,因此你最终陷入僵局。您可能只是将g_lastImage的分配插入到您的信号量的分配中,因为您似乎正确地将它们分配给它们以使它们处于进程进程中;)

+0

谢谢!这工作!我没有意识到这一点。 – tsusanka 2011-04-14 09:46:26

+0

顺便说一句,让它与更多的进程工作我将不得不张贴ChSem多次,因为我有处理权? – tsusanka 2011-04-14 09:51:09

+0

哦,当然!这些是独立的进程,而不是线程。 – 2011-04-14 09:51:41