为什么在fork()之前使用dup2()无效?

时间:2019-03-20 09:38:09

标签: c shell fork dup2

我想制作一个外壳,我想处理多个管道。我试图了解dup2()和fork的工作方式。通常,fork()创建一个与父进程完全相同的新子进程。但是当我在fork之前使用dup2时,它似乎不起作用。但是当我在子进程中使用dup2()时,它可以工作...我不明白,因为通常fork创建调用进程的副本...

有人可以解释为什么吗?

这不起作用:

int fd = open("toto.txt", O_RDONLY);
char str[10] = {0};
int test[2] = {0, 0};
char *av[] = {"/bin/ls", NULL};

pipe(test);
dup2(test[1], 1);
if (fork() == 0) {
    execve(av[0], av, env);
}
else {
    wait(NULL);
    read(test[0], str, 10);
    write(1, str, 10);
}

但这可行:

int fd = open("toto.txt", O_RDONLY);
char str[10] = {0};
int test[2] = {0, 0};
char *av[] = {"/bin/ls", NULL};

pipe(test);
if (fork() == 0) {
    dup2(test[1], 1);
    execve(av[0], av, env);
}
else {
    wait(NULL);
    read(test[0], str, 10);
    write(1, str, 10);
}

1 个答案:

答案 0 :(得分:1)

由于以下原因,原稿无法正常工作

dup2(test[1], 1);
if (fork() == 0) {
    execve(av[0], av, env);
}
else {
    wait(NULL);
    read(test[0], str, 10);
    write(1, str, 10);
}

dup2标准输出重定向到管道之后。此重定向适用于父级和子级。因此,该行:

    write(1, str, 10);

将其数据写回到管道,而不是原始的stdout(丢失)。

通过将dup2移到fork()之后,并且仅移到子进程,将保留父级的原始标准输出。在这种情况下,只会重定向孩子的标准输出。

注意:在读取管道之前调用wait可以像示例中那样处理较小的管道流量,但不适用于较大的流量。问题是管道的缓冲区有限。一旦缓冲区已满,管道就开始阻止写操作。 wait将等待子进程完成,但是子进程将等待父级读取管道。当流量足够大时,这可能会陷入僵局。