我想了解管道的工作原理,但是我不明白为什么在用“ ls -l / usr / bin”和“ grep ls”执行我的程序的情况下,waitpid会被阻塞。...选项-l可行! my_str_tab只是将字符串的每个单词放入charstar数组中。
void command_levels(int *pipe_fd, char **av, int idx, int pipe_save, int pipe_one)
{
if (idx == 1)
dup2(pipe_fd[1], 1);
else if (idx > 1 && av[idx + 1] != NULL) {
dup2(pipe_save, 0);
dup2(pipe_fd[1], 1);
}
if (idx > 1 && av[idx + 1] == NULL) {
dup2(pipe_save, 0);
dup2(pipe_one, 1);
}
}
void multiple_pipe_handle(char **av, char **env, int idx, int pipe_one)
{
int pipe_fd[2] = {0, 0};
char **command = NULL;
static int pipe_save = 0;
if (av[idx] == NULL)
return;
command = my_str_tab(av[idx], " ");
pipe(pipe_fd);
command_levels(pipe_fd, av, idx, pipe_save, pipe_one);
if (fork() == 0) {
close(pipe_fd[0]);
close(pipe_fd[1]);
execve(command[0], command, env);
} else {
wait(NULL);
close(pipe_fd[1]);
pipe_save = pipe_fd[0];
multiple_pipe_handle(av, env, idx + 1, pipe_one);
close(pipe_fd[0]);
}
}
int main(int ac, char **av, char **env)
{
int pipe_one = dup(1);
multiple_pipe_handle(av, env, 1, pipe_one);
}
我希望所有单词的输出都包含“ ls”,但我处于无限循环中。.
答案 0 :(得分:2)
这是实现管道时的常见错误。
将-l
传递给ls
时,与不传递该选项时相比,它产生的输出更多。这使其完全填满管道的内部缓冲区。内核“阻止”它继续执行,直到从管道的另一端读取某些内容为止。但是,管道的另一端尚未读取任何内容,因为您的父程序在开始ls
进程之前正在等待grep
完成执行。但是ls
将无法完成执行,直到它可以向管道中写入更多数据,因此整个程序将陷入僵局。
要修复此错误,必须先等待管道中所有进程的 all ,然后再等待其中的任何。您不能通过对multiple_pipe_handle
的单个递归调用来做到这一点。您需要两个循环,一个循环调用fork
,一个循环调用waitpid
,以及一个子进程PID数组。如果您打算从父流程中最终管道流程的输出中读取数据,则必须在开始之前读取所有产生的数据(直到read
通过返回零字节数据表示EOF信号)呼叫waitpid
。