重定向标准流
Redirecting standard stream
我正在尝试在 shell 中创建管道以重定向标准流,但我现在卡住了。
当我尝试 运行 此代码时:
int fd[2];
pid_t pid;
pipe(fd);
pid = fork();
if (pid == 0)
{
// child process
// redirect standard input and output
dup2(fd[1], STDOUT_FILENO);
dup2(fd[0], STDIN_FILENO);
// close them (they are now redirected)
close(fd[0]);
close(fd[1]);
char *input_argv[] = {"/bin/ls", "/bin/ls", ">", "out.txt", NULL};
execv(input_argv[0], input_argv);
}
else if (pid > 0)
{
// parent process
waitpid(pid, NULL,0);
}
我收到以下错误消息:
/bin/ls: cannot access >: No such file or directory
/bin/ls: cannot access out.txt: No such file or directory
我不知道它们是什么意思,是什么原因造成的,也不知道如何解决。
我做错了什么?
总而言之,代码没有任何意义。我认为这里可以给出的最佳答案是解释最有问题的部分:
// redirect standard input and output
dup2(fd[1], STDOUT_FILENO);
dup2(fd[0], STDIN_FILENO);
fd[0]
是读端,fd[1]
是一个管道的写端。您写入 fd[1]
的任何内容都可以在 fd[0]
上读取。所以,这只是 "short-circuiting" 你的 stdio 流,一点用处都没有。
通常你想用管道做的是在 parent 和 child 进程之间每个通信方向有一个管道(例如 child 应该从 parent 读取: dup2()
读端到STDIN_FILENO
在child写到写端从parent).
char *input_argv[] = {"/bin/ls", "/bin/ls", ">", "out.txt", NULL};
现在这也说不通了。 >
告诉 shell 打开文件进行写入,exec()
child 已经重定向 STDOUT_FILENO
到位。这肯定 不是 此处 ls
理解的论点。你没有shell,直接exec()
ls
就可以了
如果您的初衷是模仿 shell 在给定条件下会做什么
ls > out.txt
您应该只打开文件 out.txt
进行写入,并在 child 代码中 dup2()
您打开的文件的文件描述符 STDOUT_FILENO
在 [=21= 之前]ing ls
。在这种场景中不需要管道。
编辑 如果您想了解 shell 在内部为 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;
}
当然,实际 shell 的代码看起来不同(没有硬编码名称,使用 execv*
系列函数,因为它事先不知道参数的数量,等等。)
我正在尝试在 shell 中创建管道以重定向标准流,但我现在卡住了。
当我尝试 运行 此代码时:
int fd[2];
pid_t pid;
pipe(fd);
pid = fork();
if (pid == 0)
{
// child process
// redirect standard input and output
dup2(fd[1], STDOUT_FILENO);
dup2(fd[0], STDIN_FILENO);
// close them (they are now redirected)
close(fd[0]);
close(fd[1]);
char *input_argv[] = {"/bin/ls", "/bin/ls", ">", "out.txt", NULL};
execv(input_argv[0], input_argv);
}
else if (pid > 0)
{
// parent process
waitpid(pid, NULL,0);
}
我收到以下错误消息:
/bin/ls: cannot access >: No such file or directory
/bin/ls: cannot access out.txt: No such file or directory
我不知道它们是什么意思,是什么原因造成的,也不知道如何解决。
我做错了什么?
总而言之,代码没有任何意义。我认为这里可以给出的最佳答案是解释最有问题的部分:
// redirect standard input and output
dup2(fd[1], STDOUT_FILENO);
dup2(fd[0], STDIN_FILENO);
fd[0]
是读端,fd[1]
是一个管道的写端。您写入 fd[1]
的任何内容都可以在 fd[0]
上读取。所以,这只是 "short-circuiting" 你的 stdio 流,一点用处都没有。
通常你想用管道做的是在 parent 和 child 进程之间每个通信方向有一个管道(例如 child 应该从 parent 读取: dup2()
读端到STDIN_FILENO
在child写到写端从parent).
char *input_argv[] = {"/bin/ls", "/bin/ls", ">", "out.txt", NULL};
现在这也说不通了。 >
告诉 shell 打开文件进行写入,exec()
child 已经重定向 STDOUT_FILENO
到位。这肯定 不是 此处 ls
理解的论点。你没有shell,直接exec()
ls
就可以了
如果您的初衷是模仿 shell 在给定条件下会做什么
ls > out.txt
您应该只打开文件 out.txt
进行写入,并在 child 代码中 dup2()
您打开的文件的文件描述符 STDOUT_FILENO
在 [=21= 之前]ing ls
。在这种场景中不需要管道。
编辑 如果您想了解 shell 在内部为 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;
}
当然,实际 shell 的代码看起来不同(没有硬编码名称,使用 execv*
系列函数,因为它事先不知道参数的数量,等等。)