0

我正在尝试创建一个进程的二叉树,其中每个父进程通过管道连接到它的两个子进程。

问题:父进程 A 创建两个进程(B 和 C)和两个管道,每个进程一个。它们的文件描述符存储在 fd 中。在第二次迭代中,B 产生了它的两个孩子。B 用新管道的文件描述符覆盖存储在 fd 中的文件描述符。在生成我的 n 个级别之后,唯一剩下的管道是其父节点的叶节点(向上一级)。

我已经测试了这个理论,唯一可以交流的东西是在树的底部,叶子到上一层。我必须做到这一点,这样叶子节点才能在树上一直与主进程通信。

我是管道的新手,所以我可能会离开我的解释。

我的理解是否正确,我应该怎么做才能解决这个问题?

示例代码:

#define READ 0
#define WRITE 1

int fd[2][2];

void
spawnChildren(int levels)
{
    if(levels == 0)
       return;

    pipe(fd[0]);
    //spawns 2 children at a single parent
    int pid = fork();
    //parent
    if(pid > 0)
    {
        close(fd[0][WRITE]);
        pipe(fd[1]);
        int pid2 = fork();
        //child B
        if(pid2 == 0)
        {
            close(fd[1][READ]);
            spawnChildren(levels-1);
            return;
        }
        //parent
        else
            close(fd[1][WRITE]);
    }
    //child A
    else
    {
        close(fd[0][READ]);
        spawnChildren(levels-1);
        return;
    }
}
4

2 回答 2

0

如果我理解正确的话,根进程已经打开了两个fd 来与它的两个子进程进行通信。然后他们只是打开其他独立的管道。

当他们是四个时,根进程如何与它的侄子通信?

您需要保持所有fd 的打开状态;每个进程必须从其子进程获取输入,并将其传递给其父进程;你需要某种协议来整理它们。数据下降也是如此。

例如,根父想要与其左孩子的右孩子的左孩子进行通信:

  • 它将 RL.HELLO WORLD 发送给它的左孩子
  • 左孩子看到 R 并向其右孩子发送#L.HELLO WORLD
  • 右孩子收到#L.HELLO WORLD 并向左孩子发送##.HELLO WORLD
  • 左孩子收到##.HELLO WORLD 并知道消息是给它的

  • 左边的孩子回答发送##.I HEAR YOU给它的父母

  • 父母看到它的左孩子在说话,将最后一个#转换为L并向上发送
  • 父母看到它的右孩子说#LI HEAR YOU 并发送 RL.I HEAR YOU
  • 根从它的左孩子那里收到 RL.I HEAR YOU 并且知道是谁发起了它

当然,此时每个进程还必须有一个用于传入和传出消息的队列。

即使只在根和叶子之间进行通信也需要队列和消息传递;它只允许不使用“R#L”协议,但考虑到它的简单性,这是一个非常小的节省。

于 2012-10-03T20:21:59.580 回答
0

您需要的是一个线程或进程侦听(读取)每个管道,然后将其写入相应的管道。基本上每个“节点”都需要两个线程或进程来执行此操作,每个子节点一个。

这不是非常可扩展的,并且根据您尝试做的事情,如果您不能更好地设计它,您可能需要重新评估。一个建议是让您的叶节点写入临时文件而不是管道,然后让您的顶层智能地读取这些文件,而不是尝试通过分叉管理所有这些管道。这样做可以大量减少“节点”的数量。只是一个想法。

于 2012-10-03T20:46:24.317 回答