【问题标题】:Is dup2 the correct way to simulate the behaviour of command sequencess in a linux terminal?dup2 是在 linux 终端中模拟命令序列行为的正确方法吗?
【发布时间】:2019-03-31 12:26:46
【问题描述】:

我正在尝试在 linux 中模拟终端的行为,用 c 代码构建一个 minishell,但是在尝试实现命令序列时遇到了问题,因为第一个命令的输出不会被正确接收由下一个通过管道。我们想要实现的方法是通过管道将第一个命令(child 1)的标准输出传递给第二个命令(child 2,在 child 1 死后出生),并将其用作第二个命令的标准输入。请注意,我在 for 循环的开头使用了 fork() 语句,因此每次迭代都会创建一个孩子,该孩子会在另一个孩子出生之前死亡。

我尝试使用 dup2 以外的其他命令,但没有任何效果。此外,当使用“ls | sort”之类的命令示例并截取第一个命令的输出时,第一个命令似乎返回已经排序的列表。

argvv 是一个 char *** 类型的变量,第一级中的每个命令都包含一个条目,第二级中每个命令的每个参数都包含一个条目

/*pipes have been created already; p1, p2 (p2 only useful for sequences of 3 commands)*/

for (command_counter = 0; command_counter < num_commands; command_counter++)
        {

            int chid = fork();

            switch (chid)
            {
                case 0: // child


                //COMMAND EXECUTION


                /*Running commands with pipes */

                    /*Data is only ran through pipes if there's more than one command*/

/*we only implemented the version for two commands so far*/

                /*...*/
                if(num_commands==2)
                {
                    /*Data is only ran through pipes if there's more than one command*/
                    if(command_counter==0)
                    {//The first command takes no input from pipe
                        close(p1[0]);
                        close(p2[0]);
                        close(p2[1]);
                        dup2(p1[1], 1);
                        close(p1[1]);
                    }
                    if(command_counter==1)
                    { //Last command takes input only, output goes to stdout or output file
                        close(p2[1]);
                        close(p2[0]);
                        close(p1[1]);
                        dup2(p1[0], 0);
                        close(p1[0]);
                    }

                }


                execvp(argvv[command_counter][0], argvv[command_counter]);

                case -1:    // error
                perror("Couldn't create child process\n");
                exit(-1);

                default:
                    // father
                        waitpid(chid, 0, 0);

            }
        }
        close(p1[1]);
        close(p1[0]);
        close(p2[1]);
        close(p2[0]);

我希望程序可以正常工作,但它只是在执行排序命令时停止。我很确定错误在于使用 dup2 进行第二次迭代,但我想确定我应该怎么做才能修复它

【问题讨论】:

  • "(孩子 2,在孩子 1 死后出生)" - 这不是管道的工作方式。所有部分同时运行。
  • 我在 for 循环的开头使用了 fork() 语句,因此每次迭代都会创建一个子代,该子代会在另一个子代出生之前死亡。
  • 是的,我的意思是错的。
  • 如果第2个孩子还没有出生,则输出无处可去。

标签: c pipe stdout stdin dup2


【解决方案1】:

你做对了几件事:

  1. 您正在创建一个新进程并正确检查状态。
  2. 您有权关闭子进程和父进程不需要的管道的所有文件句柄。

你需要做对的事情:

当 child[command_counter] 创建时,它共享child[command_counter-1] 的管道(如果command_counter &gt;= 0)和child[command_counter +1] 的管道(如果command_counter +1 &lt; num_commands)。

您应该在创建最后一个孩子之后才开始等待孩子。如果您提前开始等待,则其中一个管道可能会被填满,系统将开始等待进程读取管道。但是如果最后一个孩子还没有创建,那么没有人在读管道,整个事情就会陷入僵局。 (当作者等待读取管道时,没有人在读取管道)。

如果您在开始等待之前预先创建了所有进程,那么在开始等待之前不要忘记关闭父进程中的所有管道。否则,当第一个子进程完成时,下一个子进程将不会收到 EOF 信号,因为管道仍处于打开状态(由父进程)。

【讨论】:

    猜你喜欢
    • 2022-01-19
    • 2021-12-04
    • 2018-06-25
    • 2015-05-16
    • 2014-07-03
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 2015-08-16
    相关资源
    最近更新 更多