【问题标题】:Piping problems (Broken pipe)管道问题(断管)
【发布时间】:2014-02-16 07:36:59
【问题描述】:

给定一个这种格式的命令:

cat < inputfile.txt | tee outputfile.txt

我正在尝试让 inputfile.txt 写入管道,然后从管道中读取 outputfile.txt,为此我编写了以下函数:

void piperead(char** input, int* fd, int start) {

    dup2(fd[0], 0);
    close(fd[1]);
    execl("usr/bin/tee", "usr/bin/tee", input[start + 1], NULL);

}

void pipewrite(char** input, int* fd, int start, int end) {

    dup2(fd[1], 1);
    close(fd[0]);
    execl("usr/bin/cat", "usr/bin/tee", input[start + 2], NULL);

}

void dopiping(char** input, int start, int end) {

    int fd[2];
    if (pipe(fd) == -1) {
        cout << "Error: Pipe failed." << endl;
        exit(1);
    }
    int pid = fork();
    switch(pid = fork()) {        
        case 0:
            piperead(input, fd, start, end);
        default:
            pipewrite(input, fd, end + 1);        
        case -1:
            exit(1);
    }


}

我已将命令转换为 c_strings 数组(我们称之为 cmdarray),然后调用 dopiping(cmdarray, 0, 3)。程序到达行的那一刻:

 dup2(fd[1], 1)

程序因收到 SIGPIPE 而终止。为什么我的管道坏了,我该如何解决?

【问题讨论】:

  • 您确定您的意思是"usr/bin/cat" 而不是"/usr/bin/cat"
  • 另外,您的程序有一个逻辑错误:在成功调用exec 后它将无法继续。你忘了fork吗?
  • 是的,我的意思是“/usr/......”。我是否使用 fork() 来避免逻辑错误?
  • 如果您阅读manual page for execl(3),您会看到它“用新的过程映像替换当前的过程映像”,并且该函数没有返回。您通常调用fork(2) 来创建一个新进程来执行exec 调用,这让您的主进程继续运行。
  • 好吧,我在我的 dopiping() 函数中进行了分叉,让子进程从管道中读取数据并让父进程写入管道。我的管道还是坏了,所以我不知道它是否在工作。

标签: c++ unix pipe


【解决方案1】:

所以从逻辑上看这个

  • SIGPIPE 被传递给一个对已关闭或管道/套接字执行 write() 的进程。
  • 因此,您创建的管道的读取端必须已关闭。
  • 在您执行完dup2() 后,您的代码不会关闭fd[0]
  • 所以看起来子进程正在退出。
  • 我猜execl() 失败了 - 您应该尝试指定“/usr/bin/tee”(完整路径而不是相对路径)
  • 或者您的 tee 失败 - 需要确保 input[start+1] 指向代表有效文件路径的以空字符结尾的字符串。

【讨论】:

    猜你喜欢
    • 2018-08-30
    • 1970-01-01
    • 2012-04-15
    • 1970-01-01
    • 1970-01-01
    • 2019-08-04
    • 2018-06-12
    • 2012-10-22
    • 1970-01-01
    相关资源
    最近更新 更多