C中父子进程中TAILQ队列同步的问题

问题描述 投票:0回答:1

有 5 个子进程和 1 个父进程(为了简化,我们只使用 1 个子进程)。一些计算在子进程中进行,之后它们必须将信息传递给父进程。我使用 TAILQ 队列进行消息传递。 问题是运行下面的程序会导致完全空的输出。尽管队列是在分叉之前初始化的,但我们得到的结果就好像同一队列的两个实例彼此不联系。如果您从子进程调用 TAILQ_FIRST,则一切正常。 如何同步队列?

#define _SVID_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/queue.h>

struct message
{
    int num;
    char status;
    TAILQ_ENTRY(message) queue_entry;
};

struct message_queue
{
    TAILQ_HEAD(head_t, message) head;
} queue;


int main()
{
    TAILQ_INIT(&queue.head);

    pid_t pid;
    pid = fork();

    if (!pid) // child process
    {
        while(1)
        {
            struct message* p = malloc(sizeof(struct message));
            p->num = 1;
            p->status = 's';
            TAILQ_INSERT_TAIL(&queue.head, p, queue_entry);
        }
    }
    else // parent process
    {
        while (1)
        {
            struct message* p = TAILQ_FIRST(&queue.head);

            if (p)
            {
                TAILQ_REMOVE(&queue.head, p, queue_entry);
            }

            if (p)
            {
                printf("Num %d and status %c", p->num, p->status);
                free(p);
            }
        }

    }

    return 0;
}
c synchronization queue fork
1个回答
0
投票

扩展我的评论; TAILQ 机制仅适用于单个进程,不能跨父/子进程。

我们得到好像同一队列的两个实例彼此不联系。

是的,您理解正确。

当您调用

fork()
时,它实际上创建了与第一个进程相同的第二个进程,其中包含所有程序和内存区域的副本,唯一的区别是
pid
变量的返回值:它在子进程中为零,并且父级中的非零(好吧,<0 is an error as well).

这意味着在分叉时,现在有两个队列的私有副本,并且每个进程都在其上“正确”操作,但没有操作另一端的协作进程。

我清楚地记得我试图理解单个函数以这种方式运行的概念:-)

在您的示例中,子进程能够一遍又一遍地添加消息,但没有消费者。父母正在等待某件事发生,但它永远不会发生。

如果您的任务仅限于父进程和子进程相互通信,那么管道是一个很好的机制,但如果您需要更一般的进程间通信,那么 POSIX 消息队列是一个公平的选择,但可能还有其他选择。

© www.soinside.com 2019 - 2024. All rights reserved.