有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;
}
字符串
1条答案
按热度按时间mrwjdhj31#
扩展我的评论; TAILQ机制只在单个进程中工作,而不是跨父/子进程。
我们得到的是同一个队列的两个示例,它们彼此之间没有联系。
是的,你理解的没错。
当你调用
fork()
时,它实际上创建了第二个与第一个进程相同的进程,并复制了所有程序和内存区域,唯一的区别是pid
变量的返回值:它在子进程中为零,在父进程中为非零(<0也是一个错误)。这意味着在fork上,现在有队列的两个私有副本,每个进程都在其上“正确”操作,但没有操作另一端的合作进程。
我记得很清楚,我试图让我的头周围的概念,一个单一的功能行为是这样的:-)
在你的例子中,子进程能够一遍又一遍地添加消息,但是没有消费者。父进程在等待一些事情发生,但是它永远不会发生。
如果你的任务仅限于父进程和子进程之间的通信,管道是一个很好的机制,但是如果你需要更通用的进程间通信,那么POSIX消息队列是一个不错的选择,但是可能还有其他的。