C ++管道问题

时间:2015-09-15 19:29:08

标签: c++ pipe fork

我试图分叉我的c ++程序并将父输出指向childs输入,我使用的是pipe()和fork()。在程序的目录中有一个名为input.txt的文件。不幸的是,我得到的唯一输出是" wc:stdin:读取:错误的文件描述符"。有人知道为什么吗?如果是这样,我做错了什么?谢谢

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <iostream>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>

int main(int argc, char *argv[]){

        int pipes[2],pid,stdIn,stdOut;

        stdIn = dup(0);
        stdOut = dup(1);

        pipe(pipes);

        pid = fork();

        if(pid == 0){
                dup2(pipes[1],0);
                close(pipes[1]);
                execlp("wc","wc",NULL);
        }
        else{
                dup2(pipes[0],1);
                close(pipes[0]);
                std::cout<<"input.txt"<<std::endl;
                dup2(stdOut,0);
                std::cout<<"parent done\n";
                wait(NULL);
        }

        std::cout<<"after"<<std::endl;
        return 0;
 }

2 个答案:

答案 0 :(得分:1)

您的计划中有几件事需要修复:

  1. 使用STDIN_FILENOSTDOUT_FILENO而不是0和1.这些值可能会在不同的平台上发生变化而且您也犯了一个错误,如果您使用名称而不是值,则可能会出错例如dup2(stdOut,0);重复stdin,您需要在此处复制stdout
  2. 你应该关闭孩子和父母的管道末尾
  3. 通过从wc读取stdin,然后将“input.txt”字符串传递给它 - 它将返回该字符串的统计信息,而不是文件。你可以修复它,打开该文件的文件描述符,或者使用exec* cat
  4. 您的所有调用都没有pipe()execlp()等函数检查失败。你应该这样做:

    if (pipe(pipes) == -1) {
        perror("pipe");
        exit(1);
    }
    
  5. 您不需要stdIn变量。

  6. 你会在下面找到固定的代码(它没有实现我在(5)中描述的内容):

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/wait.h>
    #include <errno.h>
    #include <string.h>
    #include <iostream>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
        int pipes[2], pid, stdOut;
    
        stdOut = dup(STDOUT_FILENO);
    
        pipe(pipes);
    
        pid = fork();
    
        if (pid == 0) {
            dup2(pipes[0], STDIN_FILENO);
            /* You need to close write end of the pipe here */
            close(pipes[1]);
            execlp("wc", "wc", NULL);
        } else {
            std::cout << "Parent setup" << std::endl;
            dup2(pipes[1], STDOUT_FILENO);
            /* You need to close write end of the pipe here as well */
            close(pipes[1]); 
            /* This will only send the string "input.txt" through the pipe, to the
             * wc command */
            std::cout << "input.txt" << std::endl;
            dup2(stdOut, STDOUT_FILENO);
            std::cout << "Parent done" << std::endl;
            wait(NULL);
        }
    
        std::cout << "Program finished" << std::endl;
        return 0;
    }
    

    编辑:正如对其他答案的评论中所建议的那样,您可以简单地使用xargs wc将stdint作为文件参数读取:

    execlp("xargs", "xargs","wc",NULL);
    

答案 1 :(得分:0)

管道向后,您已将管道的写入端连接到wc的标准输入。在wc检测到文件结束条件并正常终止之前,您需要在两个进程中关闭管道的写入端。

您还错误地将原始标准输出还原为父级的标准输入。

此外,wc默认情况下不会将标准输入解释为列表文件名,因此不会读取input.txt