我基本上想在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。
我可以做些什么来完成这项工作?
答案 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源代码的其他地方。