我一直在尝试用 C 语言开发一个迷你 shell 程序,其行为主要类似于 Bash。但是,我在执行此命令时遇到问题:
cat | ls
。在我的程序中,当我执行此命令时,它会等待来自 stdin
的输入,并且仅当 ls
到达 cat
时才打印 EOF
命令的输出,这仅在我发送 ctrl+D
时发生。向程序发出信号。另一方面,在 Bash 中,当我执行 cat | ls
命令时,它首先将 ls
命令的输出打印到 stdout
并等待来自 stdin
的输入,并在输入一个后停止执行整个命令stdin
. 的输入行
我创建了一个最小的、可重现的程序示例,它的工作方式相同。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void execute_block(char **block)
{
int pid;
pid = fork();
if (pid == -1)
exit(EXIT_FAILURE);
if (pid == 0)
{
if (execve(block[0], block, NULL) == -1)
{
perror(block[0]);
exit(127);
}
exit(EXIT_SUCCESS);
}
waitpid(pid, NULL, 0);
}
void handle_commands(char **block1, char **block2)
{
int pid;
int pipefd[2];
if (pipe(pipefd) == -1)
exit(EXIT_FAILURE);
pid = fork();
if (pid == -1)
exit(EXIT_FAILURE);
if (pid == 0)
{
close(pipefd[0]);
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
execute_block(block1);
exit(EXIT_SUCCESS);
}
close(pipefd[1]);
dup2(pipefd[0], STDIN_FILENO);
close(pipefd[0]);
waitpid(pid, NULL, 0);
execute_block(block2);
}
int main(int argc, char **argv, char **envp)
{
char *block1[] = {"/bin/cat", NULL};
char *block2[] = {"/bin/ls", NULL};
handle_commands(block1, block2);
}
为什么我的程序的行为方式与 Bash 不同。这和我处理管道的方式有关吗?或者是别的什么?另外,这个问题是否是由于我使用 waitpid() 函数的方式导致的?
你的
handle commands
代码基本上是
因此,这意味着
ls
(block2 命令)在子级(block1 命令中的 cat
)退出之前根本不会运行。
普通的 shell(如 bash)将分叉一个 second 子级并使用它来运行 block2 before waiting - 父级将在两个子级都启动后等待(对于两个子级),因此它们将同时运行