C 对管道实现感到困惑
管道的一个实现是:C 对管道实现感到困惑,c,unix,pipe,C,Unix,Pipe,管道的一个实现是: #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
#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 */
及
我被告知不再需要描述符,但对我来说,这些描述符代表管道的每一端,那么为什么不再需要它们呢?管道调用将返回用于单向通信的读描述符和写描述符。但是,写入程序不需要读取描述符fd[0]。并且,读取器不需要写入描述符fd[1]。因此,fork调用后的每个进程都会关闭它不需要的描述符,并使用它确实需要的描述符
因此,在您的示例中,家长是编写者。它首先关闭fd[0],然后关闭STD_输出。然后它复制fd[1],由于fd[1]可用,因此它现在将在STD_输出中。由于管道的输出描述符现在已复制,因此也不再需要它,因此它已关闭。现在,当编写器将某些内容写入STD_输出时,它将写入管道的输出描述符
作为读取器的子级执行类似的逻辑,但在另一个描述符上执行。它首先关闭fd[1],然后关闭STD_输入。然后它复制fd[0],这导致描述符位于STD_输入中。复制后,管道的输入描述符不再需要,所以它被关闭。现在,当读卡器从STD_输入中读取某些内容时,它将从管道的输入描述符中读取。管道调用将返回单向通信的读描述符和写描述符。但是,写入程序不需要读取描述符fd[0]。并且,读取器不需要写入描述符fd[1]。因此,fork调用后的每个进程都会关闭它不需要的描述符,并使用它确实需要的描述符
因此,在您的示例中,家长是编写者。它首先关闭fd[0],然后关闭STD_输出。然后它复制fd[1],由于fd[1]可用,因此它现在将在STD_输出中。由于管道的输出描述符现在已复制,因此也不再需要它,因此它已关闭。现在,当编写器将某些内容写入STD_输出时,它将写入管道的输出描述符
作为读取器的子级执行类似的逻辑,但在另一个描述符上执行。它首先关闭fd[1],然后关闭STD_输入。然后它复制fd[0],这导致描述符位于STD_输入中。复制后,管道的输入描述符不再需要,所以它被关闭。现在,当读卡器从STD_输入中读取某些内容时,它将从管道的输入描述符中读取。对不起,问题不明确,我已经更新了它。我了解dup前关闭的第一次使用,但不了解dup后关闭的第二次调用。@richard:您不需要两份文件描述符,是吗?一旦你复制了它,你就不需要原件了。我现在明白了,我误解了这个例子。谢谢,我很抱歉,问题不明确,我已经更新了。我了解dup前关闭的第一次使用,但不了解dup后关闭的第二次调用。@richard:您不需要两份文件描述符,是吗?一旦你复制了它,你就不需要原件了。我现在明白了,我误解了这个例子。谢谢
close(fd[0]); /* this file descriptor not needed anymore */