【问题标题】:Implementing pipe in my own shell with two child process在我自己的 shell 中用两个子进程实现管道
【发布时间】:2014-09-08 22:09:17
【问题描述】:

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

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);

【问题讨论】:

  • ll 是否别名为 ls -al
  • 是的,没错。在这种情况下它会影响吗??..'ls |排序'也有效,,
  • 我想你可能用错了execlp。第一个参数不应该是路径吗? support.sas.com/documentation/onlinedoc/sasc/doc/lr2/execlp.htm
  • 我认为如果我将 arg 放在第一个参数位置,bash 会自动找到路径。我错了吗?如果是,我该如何解决?
  • Bash 在你的程序中不能做任何事情。一旦它开始执行你的程序,你就不再使用 bash,而是使用你的 shell。

标签: c linux shell fork pipe


【解决方案1】:

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

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

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

通常,在 dup2()-ing 文件描述符之后,您需要 close() oldfd

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

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

【讨论】:

    【解决方案2】:

    你的管道逻辑是正确的。

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

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

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

    【讨论】:

    • 最好在execlp()之后打印错误信息,以防出错。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多