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

时间:2012-10-10 07:35:48

标签: c++ c fork pipe fopen

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

这就是我所做的:

#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。

我可以做些什么来完成这项工作?

3 个答案:

答案 0 :(得分:0)

Yuu可能需要使用execvp,假设foo位于PATH目录中。除此之外,您可能需要在execv("/full/path/to/foo", cmd);

中提供完整路径

答案 1 :(得分:0)

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

尝试取消比赛:

    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

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

答案 2 :(得分:0)

我已经浏览了foo的代码并提取了负责从stdin读取并写入文件的部分。您可以在此处查看文件:https://gist.github.com/3868421

我已确认echo 'some string' | foo有效,并且运行pipedata程序会将数据传输到foo并写入文件。

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