1

我基本上想在 C 中实现这一点:echo 'some string' | foo其中 foo 写入文件 file1.txt。运行 foo 使其阻塞并等待来自标准输入的输入,然后写入 file1.txt。我通过标准输入成功地向 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;
}

内部 foofopen调用本地文件并失败,错误号为 14:EFAULT。我也尝试过仅使用 popen/pclose 而不是 fork/pipe/dup2/execv 来执行此操作。

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

4

4 回答 4

0

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

于 2012-10-10T07:57:12.650 回答
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,不管任何事情。

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

于 2012-10-10T08:21:36.820 回答
0

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

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

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

于 2012-10-10T21:13:50.087 回答
0

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;
}
于 2012-10-10T22:07:28.513 回答