使用两个子进程在我自己的shell中实现管道

时间:2014-09-08 22:09:17

标签: c linux shell fork pipe

我正在编写自己的shell。以下是其中的一部分。我想用两个子进程实现管道。 但是当我执行下面的代码时,一些命令可以工作,有些则没有。 '谁|排序','ls |排序'工作,但'll | sort','cat file |排序'让我的shell停止。我必须'cntrl + c'才能从我的shell中逃脱。我不明白为什么有些命令有效,有些则不然。请有人指出我错过了什么?

int pipefd[2];
int pipePos = checkPipePos(argc, argv); //find '|' command position in argv

if (pipe(pipefd) == -1) {
        printf("Creating pipe failed\n");
        return;
    }

    if (fork() == 0) {
        close(pipefd[0]);
        dup2(pipefd[1], 1);
        execlp(argv[0], argv[0], NULL);
    }

    if (fork() == 0) {
        close(pipefd[1]);
        dup2(pipefd[0], 0);
        execlp(argv[pipePos + 1], argv[pipePos + 1], NULL);
    }

    close(pipefd[0]);
    close(pipefd[1]);

    while (wait(NULL) >= 0);

2 个答案:

答案 0 :(得分:1)

我在这里看到一个可能的问题,可能会或可能不会解释非确定性结果。

在您的子进程中,在您复制其中一个管道文件描述符之后,您并未关闭原始文件描述符。

dup2(oldfd, newfd)oldfd重复到newfd,但oldfd仍处于打开状态。 oldfdnewfd文件描述符现在都指向同一个文件。请参见dup2手册页。

通常,在使用dup2()文件描述符之后,您将要关闭()oldfd

那么,这里要发生的是,其中一个子进程在stdout和其他一些随机文件描述符上具有相同的文件描述符,而另一个子进程将拥有与stdin相同的情况。

这可能会也可能不会导致问题,具体取决于子进程的功能。真的不能说肯定,但你肯定想解决这个问题,看看它是否有帮助。

答案 1 :(得分:0)

你的管道逻辑是正确的。

ll | sort不起作用,因为ll不是可执行文件。

cat file | sort不起作用,因为您没有传递file参数。

Sam Varshavchik的改进是有效的。这是一个很好的修复,但它不会导致任何严重的问题。所有这一切导致浪费一个文件描述符插槽。