execv如何从管道获取输出?

参考旧的作业问题: /* implementing "/usr/bin/ps -ef | /usr/bin/more" */使用管道/* implementing "/usr/bin/ps -ef | /usr/bin/more" */

 #include  #include  #include  int main() { int fds[2]; int child[2]; char *argv[3]; pipe(fds); if (fork()== 0) { close(fds[1]); close(STDIN_FILENO); dup(fds[0]); /* redirect standard input to fds[1] */ argv[0] = "/bin/more"; argv[1] = NULL; /* check how the argv array is set */ execv(argv[0], argv);// here how execv reads from stdin ?? exit(0); } if (fork() == 0) { close(fds[0]); close(STDOUT_FILENO); dup(fds[1]); /* redirect standard output to fds[0] */ argv[0] = "/bin/ps"; argv[1] = "-e"; argv[2] = NULL; execv(argv[0], argv); exit(0); } close(fds[1]); wait(&child[0]); wait(&child[0]); } 

将fd重定向到标准输出后,execv如何从中读取。 是否在execv中内置它在执行命令之前从标准输入读取? 我无法得到这个概念。

你的问题基于一个错误的前提 – execv不会从任何地方读取,也不需要。 它more是从它通过调用execvinheritance的stdin读取。 morestdin读取的原因是因为它是一个filter,并且像大多数filter一样,如果未在命令行中指定另一个输入源,则默认为从stdin读取。 (否则, /usr/bin/ps -ef | /usr/bin/more将无效。)

在你的第二次fork调用中,我将改变代码:

  if (fork() == 0) { close(fds[0]); 

对此:

  close(fds[0]); if (fork() == 0) { 

ps调用的argv[1]应该是-ef

所有程序都将从stdin读取以获取终端输入并写入stdout以将数据传递到终端,如果他们没有做任何事情来更改这些流的默认设置。 代码正在做的是修改stdin以获取more并修改ps stdoutstdout for more与当前进程(父进程)相同。 因此,您的程序将ps终端输出数据重定向为终端输入以获取more

pipe调用返回两个单向连接的文件描述符。 当ps写入其stdout ,它将转到dup d fds[1] 。 当从stdin读取more ,它就是dup d fds[0] 。 所以, more的是获得ps的输出。