杀死一个进程的所有后代

时间:2015-02-14 18:06:53

标签: c linux operating-system pipe named-pipes

我正在尝试创建一个shell,其中我需要实现流水线操作.. 管道工作正常,直到所有命令都正确,否则它会阻塞或进入无限循环(当最后一个cmd错误时)..这是我的管道功能.​​... 代码说明: - 我在命令中声明的备用管道使用两个管道。初始化管道中的pipe1(fd1),当找到第二个管道时,声明另一个管道(fd2)。当发现第三个管道时,管道1(fd1)被重新声明,当找到第四个管道时,管道(fd2)被重新声明,只要找到新管道就行了。

按功能接收的num是由管道分隔的命令数(实际为数字-1)。

在循环内部,我将命令划分为五个条件

  • 1>>(奇数cmd为i%2 == 0)启动命令(i == 0和i%2 == 0)
  • 2>>结束命令(对于I%2 == 0和i == num)
  • 3>>管道中间(i%2 == 0和i!= num)
  • 4>>(偶数cmd为i%2!= 0)管道中间(i%2!= 0和i!= num)
  • 5>>结束偶数编号的cmd(i%2!= 0和i == num)

继承我的代码:

void call_piping(int num){
    int i,fd1[2],fd2[2],status;
    pid_t pid;
    //pipe(fd1);
    //pipe(fd2);
    for(i=0;i<=num;i++){
        //printf("HH\n");
        if(i%2==0){
            if(pipe(fd1)==-1){
                printf("Error creating pipe fd1\n");
                return;
            }
        }
        else{
            if(pipe(fd2)==-1){
                printf("Error creating pipe fd2\n");
                return;
            }

        }
        /*else{
            close(fd1[1]);

        }*/
        if(i==0){
            pid=fork();
            if(pid==0){
                close(fd1[0]);
                close(1);
                dup2(fd1[1],1);
                if((execvp(argv[i][0],argv[i]))==-1){
                    printf("%s: Invalid command or Command not found\n",argv[i][0]);
                    close(fd1[1]);
                    return;
                }   
            }
            else{
                waitpid(pid,&status,0);
                close(fd1[1]);
                //printf("Hello1");
            }
        }
        else if(i%2==0 && i==num){
            pid=fork();
            if(pid==0){
                close(0);
                //close(1);
                dup2(fd2[0],0);
                if((execvp(argv[i][0],argv[i]))==-1){
                    printf("%s: Invalid command or Command not found\n",argv[i][0]);
                    close(fd2[0]);
                    return;

                }
            }
            else{
                waitpid(pid,&status,0);
                //printf("Hello");
                close(fd2[0]);
            }
        }
        else if(i%2==0 && i!=num){
            pid=fork();
            if(pid==0){
                close(0);
                close(1);
                dup2(fd2[0],0);
                dup2(fd1[1],1);
                if((execvp(argv[i][0],argv[i]))==-1){
                    printf("%s: Invalid command or Command not found\n",argv[i][0]);
                    close(fd1[1]);
                    //printf("Hell");
                    close(fd2[0]);
                    return;
                }
            }
            else{
                waitpid(pid,&status,0);
                close(fd1[1]);
                //printf("Hell");
                close(fd2[0]);
            }
        }
        else if(i%2!=0 && i==num){
            pid=fork();
            if(pid==0){
                close(0);
                dup2(fd1[0],0);
                if((execvp(argv[i][0],argv[i]))==-1){
                    printf("%s: Invalid command or Command not found\n",argv[i][0]);
                    close(fd1[0]);
                    return;
                }

            }
            else{
                waitpid(pid,&status,0);
                //printf("Hel");
                close(fd1[0]);

            }


        }
        else if(i%2!=0 && i!=num){
            pid=fork();
            if(pid==0){
                close(0);
                close(1);
                dup2(fd1[0],0);
                dup2(fd2[1],1);
                if((execvp(argv[i][0],argv[i]))==-1){
                    printf("%s: Invalid command or Command not found\n",argv[i][0]);
                    close(fd2[1]);
                    close(fd1[0]);
                    return;
                }
            }
            else{
                waitpid(pid,&status,0);
                //printf("He");
                close(fd2[1]);
                close(fd1[0]);
            }

        }   

    }
}       

所以基本上它是错误处理我遇到问题...我认为是一个解决方案,所有后代进程创建但不知道该怎么做....

1 个答案:

答案 0 :(得分:0)

这是if陈述的极其复杂的老鼠窝。我当然不理解所有的代码;我甚至没有尝试过全部阅读。但是,我不认为你足够快地关闭足够的文件描述符。

例如,最后,您有:

        else{
            waitpid(pid,&status,0);
            //printf("He");
            close(fd2[1]);
            close(fd1[0]);
        }

诊断打印最后应该总是有换行符;否则,你不会及时看到输出。两个close()来电应该在waitpid()之前;在管道上等待EOF的进程如果父进程仍然打开进行写入,则不会获得EOF。

在代码的早期,你有:

        if(pid==0){
            close(fd1[0]);
            close(1);
            dup2(fd1[1],1);
            if((execvp(argv[i][0],argv[i]))==-1){
                printf("%s: Invalid command or Command not found\n",argv[i][0]);
                close(fd1[1]);
                return;
            }   
        }

根据经验,如果使用dup2()将管道文件描述符与标准输入或标准输出相关联,则应关闭该进程中管道文件描述符的两个 。在执行close(1)之前,您也无需执行dup(fd[1], 1) - dup2()无论如何都会关闭目标文件描述符。

您应该报告标准错误的错误,而不是标准输出。这个名字应该是不言自明的。

您不需要测试execvp()的返回值;除非失败,否则该函数不会返回,因此测试是多余的。退出失败的exec*()呼叫而不是返回通常也是一个好主意。如果exec*()失败并且代码返回,那么您将有两个进程竞争标准输入;这永远不会带来幸福。

第二个片段可能是这样编写的(除了其他更改之外,我还添加了一些空间以提高可读性;空间很便宜!):

        if (pid == 0)
        {
            dup2(fd1[1], 1);
            close(fd1[0]);
            close(fd1[1]);
            execvp(argv[i][0], argv[i]);
            fprintf(stderr, "%s: Invalid command or Command not found\n", argv[i][0]);
            exit(1);
        }