gpt4 book ai didi

c - 我自己的 shell 实现中的管道链接

转载 作者:行者123 更新时间:2023-11-29 09:32:36 28 4
gpt4 key购买 nike

我目前正在用 C 语言编写自己的 shell 实现。我了解管道和重定向 fds 背后的原理。但是,管道的一些特定行为引起了我的注意:

  • 猫 | ls(或任何不从 stdin 读取为管道最终元素的命令)。

在那种情况下,在 shell 中发生的事情是 ls 执行并且 cat 在退出之前请求一行(我猜是 SIGPIPE 的结果)。我试图按照本教程更好地理解多管道背后的原理:http://web.cse.ohio-state.edu/~mamrak.1/CIS762/pipes_lab_notes.html

下面是我编写的一些代码,试图复制我正在寻找的行为:

char    *cmd1[] = {"/bin/cat", NULL};
char *cmd2[] = {"/bin/ls", NULL};
int pdes[2];
pid_t child;

if (!(child = fork()))
{
pipe(pdes);
if (!fork())
{
close(pdes[0]);
dup2(pdes[1], STDOUT_FILENO);
/* cat command gets executed here */
execvp(cmd1[0], cmd1);
}
else
{
close(pdes[1]);
dup2(pdes[0], STDIN_FILENO);
/* ls command gets executed here */
execvp(cmd2[0], cmd2);
}
}
wait(NULL);

我知道该实现存在安全缺陷,但这只是为了测试。据我了解,该代码的问题在于,无论何时执行 ls,它都会退出,然后 cat 以某种方式在后台运行(在我的例子中失败,因为它在我的程序退出时尝试在 zsh 提示期间读取)。我找不到使它按应有的方式工作的解决方案。因为如果我一个一个地等待命令,比如 cat/dev/random | 这样的命令head -c 10 将永远运行...

如果有人对此问题有解决方案或至少有一些指导,我们将不胜感激。

最佳答案

在考虑了@thatotherguy 的评论后,这里是我发现在我的代码中实现的解决方案。请记住,应检查 pipefork 调用是否有错误,但此版本旨在尽可能简单。我的一些内置命令也需要额外的 exit 调用。

void    exec_pipe(t_ast *tree, t_sh *sh)
{
int pdes[2];
int status;
pid_t child_right;
pid_t child_left;

pipe(pdes);
if (!(child_left = fork()))
{
close(pdes[READ_END]);
dup2(pdes[WRITE_END], STDOUT_FILENO);
/* Execute command to the left of the tree */
exit(execute_cmd(tree->left, sh));
}
if (!(child_right = fork()))
{
close(pdes[WRITE_END]);
dup2(pdes[READ_END], STDIN_FILENO);
/* Recursive call or execution of last command */
if (tree->right->type == PIPE_NODE)
exec_pipe(tree->right, sh);
else
exit(execute_cmd(tree->right, sh));
}
/* Should not forget to close both ends of the pipe */
close(pdes[WRITE_END]);
close(pdes[READ_END]);
wait(NULL);
waitpid(child_right, &status, 0);
exit(get_status(status));
}

我对我发布的原始链接和处理链式管道的不同方法感到困惑。从我原来的问题 (http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_09_02) 下方发布的 POSIX 文档链接看来:

If the pipeline is not in the background (see Asynchronous Lists), the shell shall wait for the last command specified in the pipeline to complete, and may also wait for all commands to complete.

因此两种行为都被接受:WAITING最后一个命令,或者等待所有命令。我选择实现第二种行为以坚持 bash/zsh 的做法。

关于c - 我自己的 shell 实现中的管道链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43030966/

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