C 为什么不打印到标准输出(stdout)?

C 为什么不打印到标准输出(stdout)?,c,debugging,process,pipe,pid,C,Debugging,Process,Pipe,Pid,我目前正在创建自己的命令行shell,在尝试引入管道时遇到问题。我的程序从父进程开始。它检查用户是否输入exit或history。如果是这样,它会使用这些命令,但这并不重要。如果用户输入的不是退出或历史记录,那么它将创建一个执行当前任务的子任务 但是,如果用户输入一个具有单个管道的命令,那么我们从父进程开始,它创建一个子进程,称这个子进程为child 1。子1看到有一个管道,并使用fork创建另一个子,称这个子2。子1创建另一个子,称之为子3(注意:子2和子3使用共享内存)。现在,子2执行第一个

我目前正在创建自己的命令行shell,在尝试引入管道时遇到问题。我的程序从父进程开始。它检查用户是否输入exit或history。如果是这样,它会使用这些命令,但这并不重要。如果用户输入的不是退出或历史记录,那么它将创建一个执行当前任务的子任务

但是,如果用户输入一个具有单个管道的命令,那么我们从父进程开始,它创建一个子进程,称这个子进程为child 1。子1看到有一个管道,并使用fork创建另一个子,称这个子2。子1创建另一个子,称之为子3(注意:子2和子3使用共享内存)。现在,子2执行第一个命令,子3使用子2的输出执行命令。但由于某种原因,我没有得到任何输出

我不确定这是否是执行我任务的最有效方式,但这是我的教授说的

如果您想在此处查看我的所有代码,请访问:

否则,我的代码从子项1开始:

            //Otherwise if we have a single pipe, then do
            else if (numPipes == 1) {

                char *command1[CMD_MAX];        //string holding the first command
                char *command2[CMD_MAX];        //string holding the second command
                int fds[2];                     //create file descriptors for the parent and child
                pid_t new_pid;                  //create new pid_t obj

                onePipeSplit(tokens, command1, command2, numTokens);    //Getting each command for pipe

                if (pipe(fds) < 0) {            //use the pipe command. If < 0
                    perror("Pipe failure.");    //we have an error, so exit
                    exit(EXIT_FAILURE);
                }

                //Creating child 2
                new_pid = fork();

                //if pid < 0 then we have an error. Exit.
                if (new_pid < 0) {
                    perror("Fork failure.");
                    exit(EXIT_FAILURE);
                }

                //Else we have the child (2) process
                else if (new_pid == 0) {

                    close(fds[0]);      //Close read

                    //sending stdin to the shared file descriptor
                    if (dup2(fds[1], STDOUT_FILENO)<0) {
                        perror("Can't dup");
                        exit(EXIT_FAILURE);
                    }

                    execvp(command1[0], command1);  //Execute the next command
                    perror("Exec failure");
                    exit(EXIT_FAILURE);
                }

                //Else if we have the parent process
                else {

                    pid_t child = fork();           //Creating child 3
                    if (new_pid < 0) {              //if pid < 0, error, exit
                        perror("Fork failure.");
                        exit(EXIT_FAILURE);
                    }

                    //else if pid > 0 we have the parent wait until children execute
                    else if (new_pid > 0) {
                        wait(NULL);
                    }

                    //else we have the child (3)
                    else {

                        close(fds[1]);      //Close write

                        //Sending stdout to the shared file descriptor
                        if (dup2(fds[0], STDIN_FILENO) < 0) {
                            perror("Can't dup");
                            exit(EXIT_FAILURE);
                        }

                        execvp(command2[0], command2);  //Execute the command
                        perror("Exec failure");
                        exit(EXIT_FAILURE);
                    }
                }
            }
//否则,如果我们只有一根管道,那么就这样做
else if(numPipes==1){
char*command1[CMD_MAX];//包含第一个命令的字符串
char*command2[CMD_MAX];//保存第二个命令的字符串
int fds[2];//为父级和子级创建文件描述符
pid\u t new\u pid;//创建新的pid\u t对象
onePipeSplit(令牌、command1、command2、numTokens);//获取管道的每个命令
if(pipe(fds)<0){//使用pipe命令。if<0
perror(“管道故障”);//我们有一个错误,所以退出
退出(退出失败);
}
//创建子2
new_pid=fork();
//如果pid<0,则出现错误。退出。
如果(新的pid<0){
perror(“Fork failure”);
退出(退出失败);
}
//否则我们就有了孩子(2)的过程
else if(新的_pid==0){
关闭(fds[0]);//关闭读取
//将stdin发送到共享文件描述符
如果(dup2(fds[1],STDOUT_FILENO)0,则让父级等待直到子级执行
否则如果(新pid>0){
等待(空);
}
//否则我们就有孩子了(3)
否则{
关闭(fds[1]);//关闭写入
//将标准输出发送到共享文件描述符
如果(dup2(fds[0],标准文件号)<0){
佩罗(“不能重复”);
退出(退出失败);
}
execvp(command2[0],command2);//执行命令
perror(“执行失败”);
退出(退出失败);
}
}
}
这是我的教授给我的一张图片,展示了它应该如何工作。 问题在于:

                   pid_t child = fork();           //Creating child 3
                    if (new_pid < 0) {   
       ... you keep checking `new_pid` here on down,
       ... but you should be checking `child` here on down...
第二次之后:

command2[i] = NULL;
好的,还有一些修正:

在每次dup2()之后,需要关闭原始fd。例如:

                    if (dup2(fds[1], STDOUT_FILENO)<0) {
                        perror("Can't dup");
                        exit(EXIT_FAILURE);
                    }
                    close(fds[1]);      /* ADD ME */
问题在于:

                   pid_t child = fork();           //Creating child 3
                    if (new_pid < 0) {   
       ... you keep checking `new_pid` here on down,
       ... but you should be checking `child` here on down...
第二次之后:

command2[i] = NULL;
好的,还有一些修正:

在每次dup2()之后,需要关闭原始fd。例如:

                    if (dup2(fds[1], STDOUT_FILENO)<0) {
                        perror("Can't dup");
                        exit(EXIT_FAILURE);
                    }
                    close(fds[1]);      /* ADD ME */


我认为你的孩子太多了。如果你有
foo | bar
,你需要一个管道和两个以上的进程(除了你的程序已经有的进程)。因此,parent创建了一个管道,
p
parent分叉第一个孩子(这将是
bar
)。child:
close(p[1]);dup2(p[0],exec(“bar”);现在parent分叉第二次(这将是
foo
)。子项:
close(p[0]);dup2(p[1],1);exec(“foo”);
Parent:
close(p[0]);close[p[1]);wait for children
@J.V.A.我在问题中添加了一个图像,显示了教授给我的内容。这是否意味着总共应该有3个孩子?不过我可能错了。我不确定shell(1)函数在做什么,但如果教授希望这样做,那么这就是正确的答案:)@j、 v.a好的,你明白为什么不打印到标准输出吗?我想你的孩子太多了。如果你有
foo | bar
,你需要一个管道和两个以上的进程(除了你的程序已经是的那个)。所以家长创建一个管道,
p
家长分叉第一个孩子(这将是
bar
)。孩子:
close(p[1]);dup2(p[0],0);exec(“bar”);
现在父级第二次分叉(这将是
foo
)。子级:
close(p[0]);dup2(p[1],1);exec(“foo”);
父级:
close(p[0]);close[p[1]);wait for children
@J.V.A.我在问题中添加了一个图像,显示了教授给我的内容。这是否意味着总共应该有3个孩子?但我可能错了。我不确定是哪个函数shell(1)正在做,但如果教授希望这样做,那么这就是正确的答案:)@j.v.a好的,你知道为什么它没有打印到标准输出吗?谢谢你的回答。这修复了一个奇怪的错误,但不幸的是它仍然没有打印到标准输出。我会继续查找,但到目前为止我不确定问题是什么。你有第二个
其他问题吗如果(new_pid>0){
,对吗?是的。我刚刚尝试摆脱第二个fork,所以现在shell(2)执行第一个命令并将管道传输到shell(1)它是有效的。这真的很奇怪,当我使用2个孩子时,它不起作用…我认为如果你的教授希望这样的话,你需要保留这3个过程。我完全同意,我只是想尝试一下,看看这个错误是否在其他地方。谢谢你的回答。这修复了一个奇怪的错误,但不幸的是它仍然存在