C编程-使用管道处理stdout和stdin

C编程-使用管道处理stdout和stdin,c,linux,exec,fork,pipe,C,Linux,Exec,Fork,Pipe,我正在编写一个由父母和他的孩子组成的C程序(使用fork)。他们通过管道交流。父级通过标准输出写入管道,子级通过标准输入从管道读取。连接后,父级将“helloworld”写入管道,子级调用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

我正在编写一个由父母和他的孩子组成的C程序(使用fork)。他们通过管道交流。父级通过标准输出写入管道,子级通过标准输入从管道读取。连接后,父级将“helloworld”写入管道,子级调用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;
}
intmain(intargc,char*argv[])
{
int p,a;
char-buf[1024];
文件*文件;
尺寸(单位:nread);
int-fd[2];
字符参数[PATH_MAX];
如果(管道(fd)这不起作用,我不知道为什么

因为您使用的是
dup()
。要将子进程的标准输入重定向到管道,正确的系统调用是
dup2()

请注意,在父代码分支中根本不需要调用
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] );
有关详细信息,请阅读dup2的

另外,代码的另一个问题是使用execvp和
argv
作为参数列表。这将导致
rev
wc
等程序接收父程序的整个命令行,从而找到要处理的参数,而不是从标准输入读取的参数。您可能希望

execvp( argv[1], &argv[1] );
您在以下代码中错误地使用了
execvp()

 sprintf(argument,"/usr/bin/%s",argv[1]);
 execvp(argument,argv);
如果您通过
/a.out wc
运行程序,那么在这种情况下
/usr/bin/wc
的参数将是
/a.out wc
,即
/a.out
的原始参数列表,然后
/usr/bin/wc
将尝试在当前工作目录中打开名为
wc
的文件,而不是从标准输入读取

因此,将上述代码更改为

 sprintf(argument,"/usr/bin/%s",argv[1]);
 execvp(argument,NULL);

如果可以解决这个问题,这次
/usr/bin/wc
的参数列表将是一个空列表。

父亲仍在写入
1
而不是写入
a
,孩子也没有从管道中读取。
 sprintf(argument,"/usr/bin/%s",argv[1]);
 execvp(argument,NULL);