Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C语言中,当管道输入到另一个程序时,它无法打开_C++_C_Fork_Pipe_Fopen - Fatal编程技术网

C++ 在C语言中,当管道输入到另一个程序时,它无法打开

C++ 在C语言中,当管道输入到另一个程序时,它无法打开,c++,c,fork,pipe,fopen,C++,C,Fork,Pipe,Fopen,我主要想在C:echo'somestring'| foo中实现这一点,其中foo写入文件file1.txt。运行foo使其阻塞并等待来自stdin的输入,然后写入file1.txt。我正在通过stdin成功地向foo发送数据,但是foo在使用C管道时无法打开本地文件 以下是我所做的: #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #

我主要想在C:echo'somestring'| foo中实现这一点,其中foo写入文件file1.txt。运行foo使其阻塞并等待来自stdin的输入,然后写入file1.txt。我正在通过stdin成功地向foo发送数据,但是foo在使用C管道时无法打开本地文件

以下是我所做的:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {

    FILE *stream;
    int fds[2];
    int status;
    pid_t pid;
    char *cmd[] = { "foo", NULL };

    pipe(fds);
    pid = fork();

    if (pid < 0) {
        fprintf(stderr, "Fork failed\n");
        return 1;
    }
    if (pid > 0) {
        // Parent process
        close(fds[0]);
        stream = fdopen(fds[1], "w");
        fprintf(stream, "some string\n");
        fflush(stream);
        close(fds[1]);
        waitpid(pid, &status, 0);
        if (WIFEXITED(status) == 0 || WEXITSTATUS(status) < 0)
            return 1;
    }
    else {
        // Child process
        close(fds[1]);
        dup2(fds[0], STDIN_FILENO);

        execv("foo", cmd);
        return 1;
    }

    return 0;
}
在内部,foo对本地文件进行fopen调用,但失败,错误号为14:EFAULT。我也尝试过使用popen/pclose而不是fork/pipe/dup2/execv来实现这一点


我能做些什么来实现这一点呢?

假设foo位于PATH目录中,您可能需要使用execvp。除此之外,您可能需要在execv/full/path/to/foo,cmd中提供完整路径

代码中存在竞争条件。父进程将内容写入管道并将其关闭,而子进程从管道中读取。这可能不是你遇到问题的原因,但这从来都不是一件好事

尝试消除竞争:

    stream = fdopen(fds[1], "w");
    fprintf(stream, "some string\n");
    fflush(stream);
    waitpid(pid, &status, 0);
    close(fds[1]); // close it when the child process doesn't use it anymore
注意:不管发生什么,都应该使用fclose而不是close


编辑:正如其他人指出的,这个答案是错误的;没有争用条件。

我已经检查了foo的代码,并提取了负责从stdin读取和写入文件的部分。您可以在此处查看文件:

我已经确认echo'some string'| foo可以工作,并且运行pipedata程序可以将数据传输到foo并写入文件


由于这个例子一切正常,问题一定出在foo的源代码中的其他地方。

stdlib函数popen/pclose是完成这类工作的更简单的方法。他们为你做所有的管道和儿童管理。您的程序将变成:

#include <stdlib.h>
#include <stdio.h>

int main() {
    FILE *stream;
    if (!(stream = popen("./foo", "w"))) {
        fprintf(stderr, "popen failed\n");
        return 1;
    }
    fprintf(stream, "some string\n");
    fflush(stream);
    if (pclose(stream) < 0) {
        fprintf(stderr, "pclose failed\n");
        return 1;
    }
    return 0;
}

如果fopen因EFAULT而失败,是否可以显示fopen代码?没有管道它能工作吗?您确定提供给fopen的文件名有效吗?fopen代码看起来像fopenfile1_name,w,返回NULL。它不用管子就可以工作。提供的文件名有效。如果不想单独显示,可以将包含fopen的代码放入标记为Child process的代码部分foo的源代码很大,我不应该修改它。我们应该将其视为一个库。EFAULT仅表示传递给fopen/fdopen的无效参数,该参数将由EINVAL指示,但表示存在锁定问题。至少在Linux或POSIX确认系统上。完成子项后关闭fds[1]意味着我们永远不会通过stdin将EOF发送给foo。管道需要关闭,以便foo可以继续执行并写入由于fopen调用而失败的文件。这不是竞争条件,可以将内容写入管道并关闭其写入端。无论何时开始读取,管道的读取端都将接收数据和EOF。因为有一个fork调用,closefds[1];很好,孩子仍然有一个参考pipe@MarosHluska实际运行echo“some string”| foo工作吗?i、 e.您是否已将错误隔离在发布的代码中,并确保错误不在foo中。另一份说明;您应该关闭FDS[0];在dup2fds[0]之后的子进程中,STDIN_FILENO,否则,剩下2个文件描述符引用管道的读取端。是的,这样看起来更干净。不过,popen/close和fork/pipe解决方案都造成了问题。我已经发布了一个回复,说我让它工作了。