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

我试过使用除 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,但我想确定我应该怎么做才能修复它

请您参考如下方法:

你做对了几件事:

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

您需要做对的事情:

当 child[command_counter] 创建时,它共享 child[command_counter-1 的管道] (如果 command_counter >= 0 ),以及 child[command_counter +1] 的管道(如果 command_counter +1 < num_commands )。

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

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


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!