杀死一个进程的所有后代

时间:2021-03-21 20:57:19

I'm trying to create a shell wherein i need to implement pipelining.. The pipes are working fine untill all commands are correct else it either blocks or goes into infinite loop(when last cmd is wrong)..here's my pipelines function.... Code explanation:- I'm using two pipes for alternate pipes declared in command.Initially pipe1(fd1) in declared and when second pipe is found another pipe(fd2) is declared. When the third pipe is found pipe1(fd1 ) is redeclared and when fourth pipe is found pipe(fd2) is redeclared and this goes as long as new pipes are found.

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

num received by function is number of commands (actually number-1) separated by pipes.

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

Inside the loop then I have divided commands on five conditions

在循环内部,我在五个条件下划分了命令

  • 1>>(odd numbered cmd as i%2==0)starting command(i==0 and i%2==0)
  • 1 >>(奇数cmd为i%2 == 0)启动命令(i == 0和i%2 == 0)

  • 2>>ending command(for I%2==0 and i==num)
  • 2 >>结束命令(对于I%2 == 0和i == num)

  • 3>>mid in pipe(i%2==0 and i!=num)
  • 3 >>管道中间(i%2 == 0和i!= num)

  • 4>>(even numbered cmd as i%2!=0) mid in pipe(i%2!=0 and i!=num)
  • 4 >>(偶数cmd为i%2!= 0)管道中间(i%2!= 0和i!= num)

  • 5>>ending even numbered cmd(i%2!=0 and i==num)
  • 5 >>结束偶数编号的cmd(i%2!= 0和i == num)

Heres my code :

继承我的代码:

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]);
            }

        }   

    }
}       

so basically it is error handling i'm having problem with...one solution that i thought was to all descendants processes created but dont know how to do that....

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

1 个解决方案

#1


0  

That is an extremely complex rat's nest of if statements. I've certainly not understood all the code; I've not even attempted to read it all. However, I don't think you're closing enough file descriptors quick enough.

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

For example, at the end, you have:

例如,最后,您有:

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

Diagnostic printing should always have a newline at the end; otherwise, you won't see the output in a timely manner. The two close() calls should be before the waitpid(); processes that wait for EOF on the pipe won't get EOF if the parent process still has it open for writing.

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

Early on in the code, you have:

在代码的早期,您有:

        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;
            }   
        }

As a rule of thumb, if you use dup2() to associate a pipe file descriptor with either standard input or standard output, you should close both of the pipe file descriptors in that process. You also do not need to do close(1) before doing dup(fd[1], 1)dup2() closes the target file descriptor anyway.

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

You should report errors on standard error, not standard output. The name should be self-explanatory.

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

You don't need to test the return value from execvp(); the function won't return unless it failed, so the test is redundant. It is also usually a good idea to exit from a failed exec*() call rather than return. If the exec*() fails and the code returns, you'll have two processes competing for standard input; this never leads to happiness.

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

The second fragment might be written like this (where, amongst other changes, I've added some spaces for improved readability; spaces are cheap!):

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

        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);
        }

#1


0  

That is an extremely complex rat's nest of if statements. I've certainly not understood all the code; I've not even attempted to read it all. However, I don't think you're closing enough file descriptors quick enough.

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

For example, at the end, you have:

例如,最后,您有:

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

Diagnostic printing should always have a newline at the end; otherwise, you won't see the output in a timely manner. The two close() calls should be before the waitpid(); processes that wait for EOF on the pipe won't get EOF if the parent process still has it open for writing.

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

Early on in the code, you have:

在代码的早期,您有:

        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;
            }   
        }

As a rule of thumb, if you use dup2() to associate a pipe file descriptor with either standard input or standard output, you should close both of the pipe file descriptors in that process. You also do not need to do close(1) before doing dup(fd[1], 1)dup2() closes the target file descriptor anyway.

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

You should report errors on standard error, not standard output. The name should be self-explanatory.

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

You don't need to test the return value from execvp(); the function won't return unless it failed, so the test is redundant. It is also usually a good idea to exit from a failed exec*() call rather than return. If the exec*() fails and the code returns, you'll have two processes competing for standard input; this never leads to happiness.

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

The second fragment might be written like this (where, amongst other changes, I've added some spaces for improved readability; spaces are cheap!):

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

        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);
        }