【问题标题】:Program hangs after using pipe, fork and exec使用 pipe、fork 和 exec 后程序挂起
【发布时间】:2014-06-09 01:20:52
【问题描述】:

我正在使用 pipe fork 和 exec,为任何两个 shell 程序实现通用管道。我专门使用 ls | grep 来测试它。它起作用了,数据被复制到 grep,grep 搜索匹配项,然后将它们输出到标准输出。但是在那之后程序就挂了。

这是我在检测到管道时执行的代码。我分叉,然后再次分叉,因为我希望第一个分叉的父进程在 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;
        }
}

【问题讨论】:

标签: c linux exec fork pipe


【解决方案1】:

以下是我对问题的解决方案。我不确定这是否是永久解决方案。我什至不能 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;
        }
}

【讨论】:

  • 你忘记在你的 switch case 中放置 break @user1768079
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多