gpt4 book ai didi

c - 在抽象语法树中递归执行管道

转载 作者:行者123 更新时间:2023-11-30 14:32:56 27 4
gpt4 key购买 nike

我已经成功地为我的 minishell 制作了一个抽象语法树,事情是当我尝试执行管道命令时,我被卡住了。

第一个管道执行并将结果输出到 stdout 1,而第二个 grep filename 要么卡住要么根本不执行。

我尝试了不同的方法,得到了不同的结果,但没有一个主题有效

如果有任何帮助,我将不胜感激。

这就是我的 AST 的样子。

ls -la | cat -e | grep filename

enter image description here

t_node      *pipe_execution(t_node *node, t_list *blt, t_line *line, int std[2])
{
int pp[2];

if (node)
{
if (node->kind == NODE_PIPE)
{
if (node->and_or_command->left)
{
pipe(pp);
std[1] = pp[1];
pipe_execution(node->and_or_command->left, blt, line, std);
close(pp[1]);
}
if (node->and_or_command->right)
{
std[0] = pp[0];
std[1] = 1;
dprintf(2, "right std %d\n", std[1]);
pipe_execution(node->and_or_command->right, blt, line, std);
close(std[0]);
}
} else if (node->kind == NODE_SIMPLE_COMMAND)
{
dprintf(2, "====%s=== and stdin %d stdout %d\n", node->simple_command->head->name, std[0], std[1]);
execute_shell(blt, line->env, node, std);
}
}
return (node);
}
int        execute_shell(t_list *blt, t_list *env, t_node *node, int std[2])
{
...
return (my_fork(path, env, cmds, std));
}

我的 fork 进程的实现。

int         my_fork(char *path, t_list *env, char **cmds, int std[2])
{
pid_t child;
char **env_tab;
int status;

status = 0;
env_tab = env_to_tab(env);
child = fork();
if (child > 0)
waitpid(child, &status, 0);
else if (child == 0)
{
dup2(std[0], 0);
dup2(std[1], 1);
execve(path, cmds, env_tab);
}
return (status);
}

我希望这段代码有意义。

最佳答案

管道需要并发执行

据我从您提供的代码片段中可以看出,问题在于 my_fork()正在阻塞。因此,当您执行一个进程时,您的 shell 会停止并等待该进程完成,然后再开始下一个进程。如果你做一些简单的事情,比如:

/bin/echo Hello | cat

那么管道的内部缓冲区足够大,可以存储整个输入字符串 Hello 。一旦/bin/echo进程完成后,您执行cat ,然后可以从管道读取缓冲的数据。然而,一旦事情变得更加复杂,或者当第一个进程向管道发送更多数据时,其内部缓冲区就会满,然后就会阻塞。

解决方案是推迟调用waitpid()在您派生的进程上,直到生成属于命令行一部分的所有进程。

在启动进程之前创建所有必需的管道

您的函数pipe_execution()假设只有一个管道;它使用 filedescriptor 0 启动第一个进程。作为其输入,它使用 filedescriptor 1 启动第二个进程。作为其输出。但是,如果单个命令行上有多个管道,例如 ls -la | cat -e | grep filename ,然后输出 cat -e进程需要进入第二个管道,而不是标准输出。

您需要在启动第一个管道的右侧命令之前创建第二个管道。在启动任何命令之前创建所有管道可能是最简单的。您可以通过定义多个阶段来做到这一点:

  1. 创建管道
  2. 启动命令
  3. 等待所有命令完成

您可以多次遍历您构建的抽象语法树,每次执行其中一个阶段。

关于c - 在抽象语法树中递归执行管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59602615/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com