将多个管道连接在一起时遇到问题

Having trouble connecting multiple pipes together

我正在尝试创建一个小的 shell 程序,它可以接受多个命令并将它们链接在一起并最终执行它们。

到目前为止,我已经创建了一个列表来存储输入并将它们保存到一个名为 command 的数组中,我在其中使用 strtok 拆分输入并将结果放入一个数组中。因此,如果我输入 cat -n filename.txt,我会将 cat at command[0] -n at command[1] 和 filename.txt at command[2]。我还在每个命令的末尾添加了 NULL,(在我的 cat 示例中以命令 [3] 结束)。

我能够执行第一个命令,但如果我尝试使用第二个命令,第一个命令是唯一要执行的命令,所以我怀疑我的管道未正确链接。

这是我目前所做的:

  pid_t pid;

    int status;
    int pipes[number_arguments - 1][2];

    // Create pipes
    for (int i = 0; i < number_arguments - 1; i++)
    {
        if (pipe(pipes[i]))
        {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
    }

    // Create new processes
    for (int i = 0; i < number_arguments; i++)
    {
        pid = fork();

        if (pid == -1)
        {
            perror("fork");
            exit(EXIT_FAILURE);
        }

        if (pid == 0)
        {
             // First child
            if (i == 0)
            {
                dup2(pipes[i][WRITE_END], STDOUT_FILENO);
            }

            //Middle child
            if ((i != 0) && ((i+1) != number_arguments))
            {
                dup2(pipes[i-1][READ_END], STDIN_FILENO);
                dup2(pipes[i][WRITE_END], STDOUT_FILENO);
            }

            // Last child
            if ((i+1) == number_arguments)
            {
                dup2(pipes[i][WRITE_END], STDOUT_FILENO);
            }

            // close all pipes
            for (int j = 0; j < number_arguments - 1; j++)
            {
                close(pipes[j][READ_END]);
                close(pipes[j][WRITE_END]);
            }

            if (execvp(command[0], command) < 0)
            {
                perror("exec failure");
                exit(EXIT_FAILURE);
            }
        }
        // Parent
        else
        {
            for (int j = 0; j < number_arguments - 1; j++)
            {
                close(pipes[j][READ_END]);
                close(pipes[j][WRITE_END]);
            }
            waitpid(pid, &status, 0);
        }
    }

我很感谢能得到的任何帮助。

抱歉,如果我犯了一些错误 post,这是我的第一个 post。

您在命令启动循环之外正确地创建了管道,并且您正确地关闭了 children 中的所有管道文件描述符。后者尤其是一个常见问题。

但是,您错误地让 parent 进程在启动第一个 child 后关闭所有管道,因此第二个和后续的孩子没有管道可以使用。您还需要等待管道中的每个 child 结束,然后再启动下一个 — 您需要同时 children 到 运行。

您需要 parent 进程来启动所有 child 进程,然后才等待管道完成。

parent 进程(可能)需要记录其所有 children 的 PID。在启动所有 children 之前,它不得关闭其管道副本(但关键是它随后会这样做)。它将需要围绕 waitpid() 使用循环。它必须等到最后一个 child(管道中的最后一个进程)终止。它可能会也可能不会等到管道中所有较早的 children 也终止。

你应该做的一件事,尤其是当事情出错时,是错误检查来自系统调用的 return 值。您会发现 dup2()close() 调用在第二次迭代中失败并显示 EBADF — 错误的文件描述符。即使一切正常,检查系统调用并在它们失败时提出适当的策略也不是一个坏主意。