管道的一个实现是:
#define STD_INPUT 0
#define STD_OUTPUT 1
pipeline(char *process1, char *process2)
{
int fd[2];
pipe(&fd[0]);
if (fork() != 0) {
/* The parent process executes these statements. */
close(fd[0]);
close(STD_OUTPUT);
dup(fd[1]);
close(fd[1]); /* this file descriptor not needed anymore */
execl(process1, process1, 0);
}
else {
/* The child process executes these statements. */
close(fd[1]);
close(STD_INPUT);
dup(fd[0]);
close(fd[0]); /* this file descriptor not needed anymore */
execl(process2, process2, 0);
}
}
我对使用每个dup调用后面的两个语句感到困惑。
close(fd[1]); /* this file descriptor not needed anymore */
和
close(fd[0]); /* this file descriptor not needed anymore */
我被告知不再需要描述符,但对我来说,这些描述符代表了管道的每一端,为什么它们不再需要呢?
答案 0 :(得分:4)
pipe
调用返回单向通信的读描述符和写描述符。但是,编写器不需要读取描述符(fd[0]
)。并且,读者不需要写描述符(fd[1]
)。因此,fork
调用之后的每个进程都会关闭它不需要的描述符,并使用它所需的描述符。
所以,父亲是你的例子中的作家。它首先关闭fd[0]
,然后关闭STD_OUTPUT
。然后它会复制fd[1]
,现在它将在STD_OUTPUT
中,因为它可用。由于管道的输出描述符现在是重复的,因此不再需要它,因此它被关闭。现在,当作者向STD_OUTPUT
写入内容时,它将写入管道的输出描述符。
作为读者的孩子执行类似的逻辑,但在另一个描述符上。它首先关闭fd[1]
,然后关闭STD_INPUT
。然后它复制fd[0]
,这导致描述符在STD_INPUT
中。在复制之后,不再需要管道的输入描述符,因此它被关闭。现在,当读者从STD_INPUT
读取内容时,它将从管道的输入描述符中读取。