为什么这段代码会导致死锁? (生产者 - 消费者模型)

时间:2013-05-30 11:12:29

标签: c synchronization semaphore

我正在尝试设计5个生产者和单个消费者模型。我刚刚学会了如何从维基百科Producer-consumer problem设计模型。但我很难避免死锁。我不明白为什么这段代码导致死锁。

这是消费者。 (假设单个进程执行此代码。所有信号量和共享内存都已初始化。)

int main()
{
Shared_Data       =   (shared_data*)Shared_Address; // this is a shared memory. 
    for(i = 0 ; i < 5; i++)
    {
        sprintf(debugbuf, "%ld, filled downsem, %dth loop\n", (long)getpid(), i);
        write(STDOUT_FILENO, debugbuf, strlen(debugbuf));
        sem_wait(filled);   // try to access to the shared memory.
                            // if the shared memory is empty, consumer waits for it to be filled with pid and state.


        read.isIdle        =   I_AM_IDLE;
        read.WrittenByPid  =   Shared_Data->WrittenByPid;

        sprintf(debugbuf, "%ld, empty upsem\n", (long)getpid());
        write(STDOUT_FILENO, debugbuf, strlen(debugbuf));


        sem_post(empty);
    }
}

这是制片人。 (假设有五个进程执行此代码,并且所有信号量和共享内存都已初始化。)

int main()
{
    sprintf(debugbuf, "%ld, empty downsem\n", (long)getpid());
    write(STDOUT_FILENO, debugbuf, strlen(debugbuf));
                        // only one child process have access to here.
    sem_wait(empty);    // another child process doen't have access to here,
                        // untill parent process reads the shared memory.


    sprintf(writebuf, "%s %ld process is forked.\n", Get_CurrentTime(date), (long)getpid());
    write(STDOUT_FILENO, writebuf, strlen(writebuf));
    Put_itsState_into_SharedMemory(getpid(), I_AM_IDLE, YES_Virgin);


    sprintf(debugbuf, "%ld, filled upsem\n", (long)getpid());
    write(STDOUT_FILENO, debugbuf, strlen(debugbuf));


    sem_post(filled);
}

但我有以下结果。

32685, filled downsem, 0th loop
32687, empty downsem
32687, filled upsem
32685, empty upsem
32685, filled downsem, 1th loop
32690, empty downsem
32689, empty downsem
32691, empty downsem
32688, empty downsem
[stuck in for-loop]

任何帮助都会很棒。谢谢。

1 个答案:

答案 0 :(得分:2)

您应该始终检查sem_wait的返回值是什么。

如果您在sem_wait函数中并且有中断,则sem_wait将返回不等于0的错误。 然后,您需要使用errno检查是否发生了中断。

由于您使用fork,因此当一个子进程退出时,您可以获得SIGCHLD中断。