简体   繁体   English

使用管道,派生和执行程序后程序挂起

[英]Program hangs after using pipe, fork and exec

I am using pipe fork and exec, to implement a generic pipe for any two shell programs. 我正在使用pipe fork和exec为任何两个Shell程序实现通用管道。 I am specifically using ls | 我专门使用ls | grep to test it. grep进行测试。 It works, the data gets copied over to grep, grep searches for matches and then outputs them to stdout. 它可以正常工作,将数据复制到grep,grep搜索匹配项,然后将其输出到stdout。 However after that the program just hangs. 但是,此后程序将挂起。

This is my code that is executed when a pipe is detected. 这是我在检测到管道时执行的代码。 I fork, and then fork again because I wish to have the parent process of the first fork continue to run after the exec calls. 我分叉,然后再次分叉,因为我希望在exec调用之后让第一个分叉的父进程继续运行。 I believe due to debug code that after the exec() call that executes grep is made that nothing is happening. 我相信由于调试代码,在执行grep的exec()调用之后,什么也没发生。

    if(pipeFlag == 1){
    pipe(fd);
    PID  = fork();
        if (PID == 0){//child process
    fPID = fork();
    if(fPID == 0){//child of child
        printf("in child of child\n");
        dup2(fd[1], 1);
                execvp(command, argv);//needs error checking
                printf("mysh: %s: command not found\n", argv[0]);
            exit(EXIT_FAILURE);
    }
    if(fPID > 0){//parent of 2nd child
        printf("in parent of 2nd child\n");
        dup2(fd[0], 0);
                execvp(command1, argv1);//needs error checking
                printf("mysh: %s: command not found\n", argv[0]);
            exit(EXIT_FAILURE);
    }
    if(PID == -1){
                printf("ERROR:\n");
                switch (errno){
                    case EAGAIN:
                    printf("Cannot fork process: System Process Limit Reached\n");
                case ENOMEM:
                    printf("Cannot fork process: Out of memory\n");
                }
                return 1;
    }
        }
        if(PID > 0){//parent
            wait(PID, 0, 0);
    printf("in outer parent\n");
        }
        if(PID == -1){
            printf("ERROR:\n");
            switch (errno){
                case EAGAIN:
                printf("Cannot fork process: System Process Limit Reached\n");
            case ENOMEM:
                printf("Cannot fork process: Out of memory\n");
            }
            return 1;
        }
}

Below is my solution to the problem. 以下是我对问题的解决方案。 I'm not sure if it's a permanent solution. 我不确定这是否是永久解决方案。 I'm not even 100% sure if my reasoning for why this works and the previous code did not isn't. 我什至不是100%知道我为什么这样做和前面的代码不行。 All I did was switch the command that is waiting for input from the pipe(grep) to the parent process, and the command writing output to the pipe(ls) to the child process. 我所做的就是将正在等待输入的命令从pipe(grep)切换到父进程,并将输出信息写入pipe(ls)到子进程。

My reasoning for why this works is thus: I was testing with ls | 我之所以如此运作,是因为:我正在使用ls | grep, ls was finished writing to the pipe before grep's child process ever got set up, and therefore never closed the pipe and grep never received EOF. grep,ls在grep的子进程尚未建立之前就已经完成了对管道的写入,因此从未关闭管道并且grep从未收到EOF。 By changing their position grep was ready and waiting for ls to write by the time the process running ls is set up. 通过更改它们的位置,grep准备就绪,并在运行ls的进程建立时等待ls写入。 I believe that this is a very imperfect fix, so for anyone who reads this in the future, I hope you can provide a better answer. 我认为这是一个非常不完善的解决方案,因此对于以后阅读此书的任何人,希望您能提供更好的答案。 There are a number of conditions I can think of where this could still mess up, if my reasoning for why it works is correct. 如果我对它起作用的理由是正确的,那么我可以想到很多条件,在什么情况下仍然可能造成混乱。

 if(pipeFlag == 1){
    pipe(fd);
    PID  = fork();
        if (PID == 0){//child process
    fPID = fork();
    if(fPID == 0){//child of child
        printf("in child of child\n");
        dup2(fd[0], 0);
                execvp(command1, argv1);//needs error checking
                printf("mysh: %s: command not found\n", argv[0]);
            exit(EXIT_FAILURE);
    }
    if(fPID > 0){//parent of 2nd child
        printf("in parent of 2nd child\n");
        dup2(fd[1], 1);
                execvp(command, argv);//needs error checking
                printf("mysh: %s: command not found\n", argv[0]);
            exit(EXIT_FAILURE);
    }
    if(PID == -1){
                printf("ERROR:\n");
                switch (errno){
                    case EAGAIN:
                    printf("Cannot fork process: System Process Limit Reached\n");
                case ENOMEM:
                    printf("Cannot fork process: Out of memory\n");
                }
                return 1;
    }
        }
        if(PID > 0){//parent
            wait(PID, 0, 0);
    printf("in outer parent\n");
        }
        if(PID == -1){
            printf("ERROR:\n");
            switch (errno){
                case EAGAIN:
                printf("Cannot fork process: System Process Limit Reached\n");
            case ENOMEM:
                printf("Cannot fork process: Out of memory\n");
            }
            return 1;
        }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM