为什么管道操作在我的 shell 中不起作用?

Why are pipe operations not working in my shell?

我正在尝试shell。

这是我用于存储命令的结构:

struct command {
    char *comm;
    char *args[MAX_NO_ARGS+2];
    int no_args;
    int order;
};

在这些函数中,我 trim 基于参数和管道运算符的命令:

char *mytrim(char *s);
int get_commands(char *line, struct command mycommands[]);
void print_command(struct command mycommands[], int no_commands);

这是我执行命令和管道处理的两个函数:

void execute_commands(struct command mycommands[], int no_commands);
int execute_command(char *command, int argc, char *args[], int fd_in, int fd_out);

当我调用 execute_commands() 进行管道处理并调用 execute_command() 进行执行而不是打印时。 我卡在了无限阅读

另外,当我尝试 (ifconfig | grep "dropped") 命令时,它会打印整个 ifconfig 细节,然后无限读取。

void execute_commands(struct command mycommands[], int no_commands)
{
    if (no_commands == 1) {
        execute_command(mycommands[0].comm, mycommands[0].no_args, mycommands[0].args, -1, -1);
    } else {
        int i = 0, j = 0;
        int fd[no_commands-1][2];
        for (i = 0; i < no_commands; i++) {
            pipe(fd[i]);

        }
        for (i = 0; i < no_commands; i++) {
            if (i == 0) {
                execute_command(mycommands[i].comm, mycommands[i].no_args, mycommands[i].args, -1, fd[i][1]);
            } else if (i == no_commands -1 ) {
                execute_command(mycommands[i].comm, mycommands[i].no_args, mycommands[i].args, fd[i-1][0], -1);
            } else {
                execute_command(mycommands[i].comm, mycommands[i].no_args, mycommands[i].args, fd[i-1][0], fd[i][1]);
            }
        }

        for (i = 0; i < no_commands-1; i++) {
            close(fd[i][0]);
        }
    }
    return;
}

int execute_command(char *command, int argc, char *args[], int fd_in, int fd_out)
{
    int pid;
    pid = fork();
    if (pid == 0) {
        if (fd_in) {
            close(fd_in);
            dup2(fd_in, STDIN_FILENO);
            execvp(command, args);
        }
        if (fd_out) {
            close(fd_out);
            dup2(fd_out, STDOUT_FILENO);
            execvp(command, args);
        }
        if (fd_in == fd_out == -1) {
            execvp(command, args);
        }
    }
    waitpid(pid, NULL, 0);
    return 0;
}

您关闭 fds 的顺序错误。你写:

    close(fd_in);
    dup2(fd_in, STDIN_FILENO);

但你需要先复制:

    dup2(fd_in, STDIN_FILENO);
    close(fd_in);

此外,逻辑看起来很可疑。而不是:

 if (fd_out) {

你可能想要

if (fd_out != 1) {

检查 if (fd_in == fd_out == -1) 几乎肯定不会像您认为的那样。 (我的意思是,您可能认为它正在检查 (fd_in == -1 && fd_out == -1),但事实并非如此)。您需要检查从 pipe 返回的值而不是文件描述符的值。

此外,在多个地方使用 exec 也是不正确的。您的代码当前的结构方式,假设没有错误,fd_in 将始终为非零,并且您的代码在重复 fd_in 后将 exec。它甚至永远不会检查 fd_out,当然也永远不会将其复制为 stdout。您应该删除 if 子句中的 exec,并且只调用一次 exec。在 exec 之后你唯一应该写的代码是 perror("exec"); exit(EXIT_FAILURE);

您还应该关闭父进程中的 fd_in 和 fd_out