我正在用C写一些程序来学习子进程,下面的代码有点问题。这个想法是使用exec、未命名管道和copy2来模拟bash命令,但不知何故,只有当我删除第二个和第三个等待(NULL)时,程序才能正常工作。
int pipe_fd[2][2];
enum {READ, WRITE};
void ls() {
close(pipe_fd[0][READ]);
dup2(pipe_fd[0][WRITE], STDOUT_FILENO);
execlp("ls", "ls", "-al", NULL);
}
void grep() {
close(pipe_fd[0][WRITE]);
close(pipe_fd[1][READ]);
dup2(pipe_fd[0][READ], STDIN_FILENO);
dup2(pipe_fd[1][WRITE], STDOUT_FILENO);
execlp("grep", "grep", "e", NULL);
}
void wc() {
close(pipe_fd[1][WRITE]);
dup2(pipe_fd[1][READ], STDIN_FILENO);
execlp("wc", "wc", "-l", NULL);
}
int main(void) {
pipe(pipe_fd[0]);
pipe(pipe_fd[1]);
pid_t pid_ls = fork();
if (pid_ls < 0) exit(EXIT_FAILURE);
else if (pid_ls == 0) ls();
wait(NULL);
pid_t pid_grep = fork();
if (pid_grep < 0) exit(EXIT_FAILURE);
else if (pid_grep == 0) grep();
wait(NULL);
close(pipe_fd[0][WRITE]);
close(pipe_fd[0][READ]);
pid_t pid_wc = fork();
if (pid_wc < 0) exit(EXIT_FAILURE);
else if (pid_wc == 0) wc();
wait(NULL);
close(pipe_fd[1][WRITE]);
close(pipe_fd[1][READ]);
exit(EXIT_SUCCESS);
}
我不太确定是什么问题。我很确定即使在运行exec()之后我仍然需要等待()
1条答案
按热度按时间pjngdqdw1#
提前打开管道意味着,在关闭管道之前,每个子节点都将接收到每个打开的文件描述符的副本(管道的开放端)。
然后,每个子进程必须关闭它没有使用的每个文件描述符,否则管道的另一端将保持打开状态,导致正在使用该特定描述符对的进程阻塞,等待更多数据。
您还必须关闭指定给
dup2
的 old 文件描述符(第一个参数),否则它和 new 文件描述符(第二个参数)都将打开,指向相同的文件描述。你应该在关闭父进程中的所有管道后再收获你的子进程。
更完整地(尽管为了简洁起见跳过了一些错误处理):