如何管理管道上升和管道进入二进制树流程?

时间:2012-10-03 19:55:31

标签: c fork pipe file-descriptor

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

问题:父进程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;
    }
}

2 个答案:

答案 0 :(得分:0)

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

当他们时,根进程如何与其侄子沟通?

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

例如,根父母希望与其左孩子的右孩子的左孩子进行交流:

  • 它将RL.HELLO WORLD发送给其左边的孩子
  • 左边的孩子看到R并将#L.HELLO WORLD发送给其右边的孩子
  • 正确的孩子收到#L.HELLO WORLD并将##。HELLO WORLD发送给其左侧孩子
  • 左边的孩子收到了##。HELLO WORLD并且知道了它的消息

  • 左边的孩子回答发送##。我听你的父母

  • 父母看到其左边的孩子说话,将最后一个#转换为L并发送
  • 父母看到正确的孩子说#L。听到你的声音并发送RL.I听你说。
  • 根收到RL。我从左边的孩子那里听到你,知道是谁发起的

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

即使只在root和leaves之间进行通信也需要队列和消息传递;它只允许没有“R#L”协议,但鉴于其简单性,这是一个非常小的节省。

答案 1 :(得分:0)

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

这不是很容易扩展,根据你想要做的事情你可能想要重新评估一下你是否能够更好地设计它。一个建议是让您的叶节点写入临时文件而不是管道,然后让您的顶层智能地读取这些文件,而不是试图通过分支管理所有这些管道。这样做可以大量减少“节点”的数量。只是一个想法。