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
是从它通过调用execv
inheritance的stdin
读取。 more
从stdin
读取的原因是因为它是一个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
stdout
。 stdout
for more
与当前进程(父进程)相同。 因此,您的程序将ps
终端输出数据重定向为终端输入以获取more
。
pipe
调用返回两个单向连接的文件描述符。 当ps
写入其stdout
,它将转到dup
d fds[1]
。 当从stdin
读取more
,它就是dup
d fds[0]
。 所以, more
的是获得ps
的输出。