程序在使用pipe,fork和exec后挂起

时间:2014-04-23 23:54:44

标签: c linux exec fork pipe

我正在使用pipe fork和exec,为任何两个shell程序实现通用管道。我特意使用ls | grep来测试它。它工作,数据被复制到grep,grep搜索匹配,然后将它们输出到stdout。然而,之后该程序就会挂起。

这是我检测到管道时执行的代码。我fork,然后再次fork,因为我希望第一个fork的父进程在exec调用之后继续运行。我相信由于调试代码,在执行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;
        }
}

1 个答案:

答案 0 :(得分:0)

以下是我解决问题的方法。我不确定它是否是一个永久的解决方案。我甚至不能100%确定我的理由是否有效以及之前的代码没有。我所做的只是将等待来自管道(grep)的输入的命令切换到父进程,并将命令写入管道(ls)到子进程。

我为什么这样做的原因是:我正在测试ls | grep,ls在grep的子进程设置之前已完成写入管道,因此从未关闭管道并且grep从未接收到EOF。通过改变它们的位置,grep已经准备就绪并且等待ls在设置进程ls的时候写入。我相信这是一个非常不完美的解决方案,所以对于将来读这篇文章的人,我希望你能提供更好的答案。如果我对其工作原理的推理是正确的,那么我可以想到一些条件,这可能仍然会陷入困境。

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