c - 3个子进程之间的管道

时间:2014-10-17 02:25:34

标签: c pipe

我似乎无法找到如何通过三个子进程管道数据的良好解释。我基本上想要这样做:

ls -al / | tr a-j A-J | tr k-z K-Z

我已经能够设置两个子进程来模拟命令的前两部分,并且输出正确。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

main()
{
    int pi[2];
    pipe(pi);

    //  First child
    if ( fork() == 0 )
    {
        close(pi[0]);
        dup2(pi[1], 1);
        close(pi[1]);
        execlp( "ls", "ls", "-al", NULL );
    }

    //  Second child
    if ( fork() == 0 )
    {
        close(pi[1]);
        dup2(pi[0], 0);
        close(pi[0]);
        execlp( "tr", "tr", "a-j", "A-J", NULL );
    }

    //  Close parent's copy of pipe
    close(pi[0]);
    close(pi[1]);

    wait(NULL);
}

我能想到将输出传递给第三个进程的唯一方法是创建第二个管道。然后我会使用第二个管道将数据从第二个子项传递给第三个子项。不幸的是,当我尝试这样做时,我根本没有输出。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

main()
{
    //  Create the two pipes
    int pi[2];
    pipe(pi);
    int pi2[2];
    pipe(pi2);

    //  First child
    if ( fork() == 0 )
    {
        //  Set up the first pipe to be written to
        close(pi[0]);
        dup2(pi[1], 1);
        close(pi[1]);
        execlp( "ls", "ls", "-al", NULL );
    }

    //  Second child
    if ( fork() == 0 )
    {
        //  Set up first pipe to be read from
        close(pi[1]);
        dup2(pi[0], 0);
        close(pi[0]);
        //  Set up second pipe to be written to
        close(pi2[0]);
        dup2(pi2[1], 1);
        close(pi2[1]);
        execlp( "tr", "tr", "a-j", "A-J", NULL );
    }

    //  Third child
    if ( fork() == 0 )
    {
        //  Set up second pipe to be read from
        close(pi2[1]);
        dup2(pi2[0], 0);
        close(pi2[0]);
        execlp( "tr", "tr", "k-z", "K-Z", NULL );
    }

    //  Close parent's copy of first and second pipes
    close(pi[1]);
    close(pi[0]);
    close(pi2[1]);
    close(pi2[0]);

    wait(NULL);
}

我不完全确定从哪里开始。是编码错误,还是错误的方法?

编辑:我发现了问题。管道(pi)上的端点被复制到子进程中,永远不会关闭。解决方案是在分叉第三个子节点之前关闭父节点中的端点,这样它就不会获得自己的副本,或者关闭端点的副本。

我已经在第三个孩子面前关闭了端点。我也没有制造烟斗&#34; pi2&#34;直到第一个实际使用它的孩子之后。我认为理论上我应该关闭管道的端点&#34; pi2&#34;在第一个孩子,但在实践中它仍然有效。将管道的创建移动到第一个子项之后将消除任何问题。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

main()
{
    //  Create the two pipes
    int pi[2];
    pipe(pi);
    int pi2[2];

    //  First child
    if ( fork() == 0 )
    {
        //  Set up the first pipe to be written to
        //  and close the unneeded pipe endpoints
        close(pi[0]);
        dup2(pi[1], 1);
        close(pi[1]);
        execlp( "ls", "ls", "-al", NULL );
    }

    //  Don't open the second pipe until it's needed
    //  so extra endpoints don't need to be closed
    pipe(pi2);

    //  Second child
    if ( fork() == 0 )
    {
        //  Set up first pipe to be read from
        //  and close the unneeded pipe endpoints
        close(pi[1]);
        dup2(pi[0], 0);
        close(pi[0]);
        //  Set up second pipe to be written to
        //  and close the unneeded pipe endpoints
        close(pi2[0]);
        dup2(pi2[1], 1);
        close(pi2[1]);
        execlp( "tr", "tr", "a-j", "A-J", NULL );
    }

    //  Close original pipe endpoints so they aren't
    //  duplicated into the third child (where they would
    //  need to be closed).
    close(pi[1]);
    close(pi[0]);

    //  Third child
    if ( fork() == 0 )
    {
        //  Set up second pipe to be read from
        //  and close the unneeded pipe endpoints
        close(pi2[1]);
        dup2(pi2[0], 0);
        close(pi2[0]);
        execlp( "tr", "tr", "k-z", "K-Z", NULL );
    }

    //  Close parent's copy of second pipes
    close(pi2[1]);
    close(pi2[0]);

    wait(NULL);
}

0 个答案:

没有答案