我认为应该打开该文件,并且dup2
使用的方法,但不知道用什么方法
您对实现重定向的机制是正确的。它应该在预期的过程中完成tr
,并在执行叠加之前。
让我们一步一步来:
ls | tr a b > text.txt
首先创建一个管道,然后fork()
.
从现在开始,有two流程并行运行,两者最终都会overlaid借助于exec()
: 之一与ls
程序,另一个与tr
程序。
流程为ls
:
- 关上阅读结束管道的:此进程只会写入管道。
-
dup2()
the 写作结束的管道至STDOUT
:该进程写入的内容STDOUT
正在写入管道。
- 执行叠加:
exec()
with ls
.
流程为tr
:
- 关上写作结束管道的:此进程只会从管道中读取。
-
dup2()
the 阅读结束的管道至STDIN
:该进程读取的内容STDIN
来自管道。
为了执行重定向 to the text.txt
文件,首先open()
文件text.txt
用于书写和带有旗帜O_CREAT
and O_TRUNC
, then dup2()
获取到的文件描述符STDOUT
.
执行叠加:exec()
with tr
.
请注意,如果命令附加到text.txt
而不是截断它(即:使用>>
代替>
):
ls | tr a b >> text.txt
你必须使用该标志O_APPEND
代替O_TRUNC
when open()
ing the text.txt
file.
代码片段
我修改了你的代码(还有接口fork_pipes()
)。这是一个运行的最小示例,我希望它有所帮助。
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int spawn_proc (int in, int out, char** cmd) {
pid_t pid;
if ((pid = fork ()) == 0) {
if (in != 0) {
dup2 (in, 0);
close (in);
}
if (out != 1) {
dup2 (out, 1);
close (out);
}
return execvp (cmd[0], cmd);
}
return pid;
}
void fork_pipes (char** cmd[], const char *redirection) {
int i, n;
int in, out, fd[2];
in = 0;
// obtain n from the NULL terminated cmd array
for (n = 0; cmd[n]; ++n)
;
// process all but the last elemet of the pipe
for (i = 0; i < n-1; ++i) {
pipe(fd);
spawn_proc(in, fd[1], cmd[i]);
close(fd [1]);
in = fd [0];
}
// process the last element of the pipe
if (redirection) {
out = open(redirection, O_WRONLY | O_CREAT | O_TRUNC);
fchmod(out, 0666);
} else
out = STDOUT_FILENO;
if (in != 0)
dup2(in, 0);
spawn_proc(in, out, cmd[i]);
}
int main()
{
char *cmd1[] = {"ls", NULL};
char *cmd2[] = {"tr", "a", "b", NULL};
char **cmd[] = { cmd1, cmd2, NULL};
// redirected to text.txt
fork_pipes(cmd, "text.txt");
// no redirection
fork_pipes(cmd, NULL);
// another example with a longer pipe
{
char *cmd1[] = {"echo", "hello world", NULL};
char *cmd2[] = {"tee", NULL};
char *cmd3[] = {"tee", NULL};
char *cmd4[] = {"tr", "lo", "10", NULL};
char **cmd[] = {cmd1, cmd2, cmd3, cmd4, NULL};
// redirected to redirection.txt
fork_pipes(cmd, "redirection.txt");
// no redirected
fork_pipes(cmd, NULL);
}
return 0;
}
正如已经指出的这条评论 https://stackoverflow.com/questions/47478392/redirection-at-the-end-of-the-pipe-c-shell/47478908#comment81926358_47478392。你只需要打电话pipe()
在你的例子中一次:pipe()
只需要调用系统调用once对于每个管道操作员(即:|
字符)在复合命令中找到。例如,在以下命令中:
cmd1 | cmd2 | cmd3 | cmd4
pipe()
必须恰好被调用四次,因为有四个管道操作员.