总而言之,代码没有任何意义。我认为最好的答案可以在这里给出的解释最有问题的部分:
// redirect standard input and output
dup2(fd[1], STDOUT_FILENO);
dup2(fd[0], STDIN_FILENO);
fd[0]
是读取结束,fd[1]
管道的书写端。无论您写给fd[1]
是否可在fd[0]
上阅读。所以,这只是“短路”你的stdio流,根本不是有用的东西。
你想管做的通常是具有每父子进程(如之间的通信方向的管的孩子应该从父母阅读:在孩子dup2()
阅读结束STDIN_FILENO
并写入到从书写结束父母)。
char *input_argv[] = {"/bin/ls", "/bin/ls", ">", "out.txt", NULL};
现在这也没有意义。 A >
告诉shell打开一个写入文件,并且exec()
已经存在重定向STDOUT_FILENO
的孩子。肯定是而不是在这里可以被ls
理解。你没有一个外壳,你直接exec()
ls
。
如果你的初衷是为了模仿给出
ls > out.txt
壳时会做什么
你应该打开文件out.txt
写入和孩子码dup2()
之前,你打开的文件的文件描述符STDOUT_FILENO
exec()
ing ls
。在这个场景中不需要管道。
编辑如果你想了解什么壳内部确实为ls > out.txt
:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
int main(void)
{
/* open file for writing */
int outfd = open("/tmp/out.txt", O_CREAT|O_WRONLY, 00666);
if (outfd < 0)
{
perror("open()");
return EXIT_FAILURE;
}
/* fork child */
int pid = fork();
if (pid < 0)
{
perror("fork()");
return EXIT_FAILURE;
}
if (pid == 0)
{
/* in the child, redirect stdout to our file */
if (dup2(outfd, STDOUT_FILENO) < 0)
{
perror("dup2()");
return EXIT_FAILURE;
}
close(outfd);
/* then execute 'ls' */
execlp("ls", "ls", 0);
/* only reached when execlp() fails: */
perror("execlp()");
return EXIT_FAILURE;
}
/* we don't need the output file in the parent process: */
close(outfd);
/* wait for child to complete */
int childrc;
waitpid(pid, &childrc, 0);
/* return exit code of child process */
return childrc;
}
当然,实际的壳的代码看起来不同的(没有硬编码名称,使用execv*
函数族,因为它不提前知道参数的数量,等等。)