C++管道问题

C++ piping issue

我正在尝试分叉我的 C++ 程序并将父级输出定向到子级输入,我正在使用 pipe() 和 fork()。在程序的目录中有一个名为 input.txt 的文件。不幸的是,我得到的唯一输出是 "wc: stdin: read: Bad file descriptor"。有人知道为什么吗?如果是这样,我做错了什么?谢谢

#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;
 }

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

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

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

您的程序中有几个问题需要修正:

  1. 使用 STDIN_FILENOSTDOUT_FILENO 而不是 0 和 1。这个值在不同的平台上可能会改变,你也犯了一个错误,如果你使用名称而不是值,例如dup2(stdOut,0); 复制了 stdin,您需要在此处复制 stdout
  2. 您应该关闭子进程和父进程的管道写端
  3. 通过使 wcstdin 读取,然后您将 "input.txt" 字符串传递给它 - 它会 return 该字符串的统计信息,而不是文件的统计信息。您可以通过打开该文件的文件描述符或使用 exec*cat.
  4. 来修复它
  5. None 调用 pipe()execlp() 等函数检查失败。你应该这样做:

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

您会在下面找到固定代码(它没有实现我在 (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);