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

标签 c linux exec fork pipe

我正在编写一个由 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 作为参数列表。这将导致像 revwc 这样的程序接收父程序的整个命令行,从而找到要处理的参数,而不是从标准输入读取。您可能想要

execvp( argv[1], &argv[1] );

关于C 编程 - 使用管道处理 stdout 和 stdin,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23156620/

相关文章:

c - 为什么我们调用 Signal Handler 两次?

linux - 带有 Open MPI 1.8.4 的 DRBL 集群

linux - 通过剪切从给定文件中删除单词

php - 使用 exec() 调用 python 脚本时出错

c - 强制使用 `exec` 创建的程序执行无缓冲 I/O

c - 如何找到用户输入的字符串中的第一个重复字符?

c - 如何在客户端处理传统 OCSP 和 OCSP 装订

c - OpenMP 部分运行速度比单线程慢

linux - 无法创建裸 git 存储库

node.js - 为什么 execSync 在我的代码中不起作用?