我的程序有些问题。
我有一个学校作业,我必须重现bash的一些特性作业几乎完成了,但我有一个问题,与内置的命令和管道确实我有一个坏管道错误,每当内置的命令是最后一个管道这样:ls|echo(此行将产生管道破裂错误),其中echo|ls将工作得很好。经过一些研究,我发现了什么问题,我有这个错误,因为为内置命令(意味着我不使用execve来调用它们)当其他命令被分叉时,我不将它们分叉到子进程中,所以我猜测是,当ls还在写入管道时,build_command关闭管道read_end的速度太快了。我处理这个错误的方法是为内置命令派生一个进程。但是我想知道它们是否是一个不派生内置命令的解决方案,因为这会使用不必要的资源。
void execute_routine(t_data *data, t_cmd *cmd)
{
pid_t pid_ret;
if (data -> s_pipes && !ft_strcmp(cmd -> prev_stop, "|")
&& cmd -> prev_cmd -> p_close)
close_fd(data, "bash", &data -> s_pipes -> s_pipes[1]);
if (!built_in(data, cmd, 0))
{
pid_ret = fork();
if (pid_ret < 0)
print_err_and_exit(data, NULL, "bash", 1);
if (pid_ret == 0)
forking(cmd);
cmd -> pid = pid_ret;
}
handle_pipes(data, cmd);
}
在上面,是通过readline的帮助执行每个命令get的函数,你可以看到,如果命令是内置的,我们不会派生它,它将被直接处理到该函数中,对于echo的情况,下面是该函数:
int echo(t_data *data, t_cmd *cmd)
{
int fd;
data -> status = 1;
if (open_check_files_built_in(cmd, cmd -> tab))
return (1);
fd = where_to_write(data, cmd);
if (ft_tab_len(cmd -> args) == 1)
{
if (write_to_fd(data, "\n", fd) < 0)
return (print_err_built_in("bash", 1));
data -> status = 0;
return (1);
}
if (write_args_(data, cmd, fd))
return (1);
if (cmd -> last_in && cmd -> last_in -> type == IN)
close_fd_built_in(&cmd -> last_in -> fd);
if (cmd -> last_out)
close_fd_built_in(&cmd -> last_out -> fd);
data -> status = 0;
return (1);
}
对于echo,我只寻找输出重定向和写入返回的fd。当我完成函数时,我在该函数中使用管道。
void handle_pipes(t_data *data, t_cmd *cmd)
{
if (data -> s_pipes && data -> prev_pipes == -1
&& !ft_strcmp(cmd -> prev_stop, "|"))
close_fd(data, "bash", &data -> s_pipes -> read_end -> s_pipes[0]);
close_fd(data, "bash error", &data -> prev_pipes);
if (data -> inited)
{
data -> prev_pipes = data -> pipes[0];
close_fd(data, "bash pipes close", &data -> pipes[1]);
}
data -> inited = 0;
}
之后,我等待我的所有进程与下面的函数
int i;
i = -1;
while (cmds[++i])
{
if (cmds[i]-> pid && waitpid(
cmds[i]-> pid, &data -> status, 0) < 0 && errno != ECHILD)
print_err_and_exit(data, NULL, "Error with waitpid", 1);
}
正如我前面所说的,built_in命令和其他命令之间的唯一区别是,built_in命令不是在父进程中派生和直接处理的,而其他命令是在子进程中派生和处理的。尽管我有管道破裂错误信号,但管道仍然输出预期的结果,例如ls|echo bonjour仍然会将bonjour输出到STDOUT,但处理ls命令的进程会将错误SIGPIPE发送到waitpid,而echo bonjour|ls也将工作良好,并返回状态代码0而不是13。
1条答案
按热度按时间bxjv4tth1#
问题是您误解了“echo”的性质与“ls"的性质,以及“pipes”的性质
“ls”可能是多行函数。它生成流。
“管道”是一种在一个进程创建流 * 和另一个进程使用该流作为输入 * 之间创建进程间通信的机制。
以下是你未能理解“echo"本质的地方:echo不是一个面向多行(也叫流)的工具!它是一个单行工具,适合于一个“单”参数字符串。该字符串可以是多行的,但它被传递给echo,echo只将其解释为一个单参数,而不关心其内容是什么。
甚至手册页**也没有提到echo接受来自stdin的输入!*换句话说, 它甚至没有打开管道流 *。
希望这能澄清你所认为的关于“s”的谜团|echo”管道。