我正在编写一个由 parent 和他的 child 组成的C程序(使用fork)。他们通过管道进行通信。父级通过标准输出写入管道,子级通过标准输入从管道读取。连接后,父进程将“hello world”写入管道,子进程调用 exec。我的代码如下所示:
int main(int argc, char *argv[])
{
int p, a;
char buf[1024];
FILE *file;
size_t nread;
int fd[2];
char argument[PATH_MAX];
if(pipe(fd)<0){
return 1;
}
p = fork();
switch(p){
case -1: perror("Error en el fork()"); return 1;
case 0:
close(fd[1]);
close (0);
dup(fd[0]);
close(fd[0]);
sprintf(argument,"/usr/bin/%s",argv[1]);
execvp(argument,argv);
perror("Error en el execv");
exit(1);
default: break;
}
close(fd[0]);
close(1);
a = dup(fd[1]);
close(fd[1]);
write(1,"Hello World\n",12);
close(a);
wait(NULL);
return 0;
}
子执行的exec函数调用函数rev或wc。如果不带参数调用,则 rev 和 wc 应应用于标准输入(在我的例子中为“hello world”)。但这不起作用,我不知道为什么。任何帮助将不胜感激。
最佳答案
这不起作用,我不知道为什么
因为您正在使用dup()
。要将子进程的标准输入重定向到管道,正确使用的系统调用是dup2()
case 0:
close( fd[1] );
dup2( fd[0], 0 ); // this "dup"s the read-end of the pipe onto STDIN
close( fd[0] );
请注意,您根本不需要在父代码分支中调用 dup()
。只需写入管道的写入端即可:
write( fd[1], "Hello World\n", 12 );
但是,如果您还想在父分支中使用 execvp,启动另一个程序并重定向其标准输出,那么您还必须在此处使用 dup2()
:
dup2( fd[1], 1 ); // this "dup"s the write-end of the pipe onto STDOUT
close( fd[1] );
阅读manpage有关详细信息,请参阅 dup2
。
此外,代码的另一个问题是使用 execvp 和 argv 作为参数列表。这将导致像 rev
和 wc
这样的程序接收父程序的整个命令行,从而找到要处理的参数,而不是从标准输入读取。您可能想要
execvp( argv[1], &argv[1] );
关于C 编程 - 使用管道处理 stdout 和 stdin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23156620/