c-程序在使用pipe、fork和exec后挂起



我使用管道fork和exec来实现任意两个shell程序的通用管道。我特别使用ls|grep来测试它。它有效,数据被复制到grep,grep搜索匹配项,然后将它们输出到stdout。然而,在那之后,程序就挂起了。

这是我在检测到管道时执行的代码。我分叉,然后再次分叉,因为我希望第一个分叉的父进程在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 childn");
        dup2(fd[1], 1);
                execvp(command, argv);//needs error checking
                printf("mysh: %s: command not foundn", argv[0]);
            exit(EXIT_FAILURE);
    }
    if(fPID > 0){//parent of 2nd child
        printf("in parent of 2nd childn");
        dup2(fd[0], 0);
                execvp(command1, argv1);//needs error checking
                printf("mysh: %s: command not foundn", argv[0]);
            exit(EXIT_FAILURE);
    }
    if(PID == -1){
                printf("ERROR:n");
                switch (errno){
                    case EAGAIN:
                    printf("Cannot fork process: System Process Limit Reachedn");
                case ENOMEM:
                    printf("Cannot fork process: Out of memoryn");
                }
                return 1;
    }
        }
        if(PID > 0){//parent
            wait(PID, 0, 0);
    printf("in outer parentn");
        }
        if(PID == -1){
            printf("ERROR:n");
            switch (errno){
                case EAGAIN:
                printf("Cannot fork process: System Process Limit Reachedn");
            case ENOMEM:
                printf("Cannot fork process: Out of memoryn");
            }
            return 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 childn");
        dup2(fd[0], 0);
                execvp(command1, argv1);//needs error checking
                printf("mysh: %s: command not foundn", argv[0]);
            exit(EXIT_FAILURE);
    }
    if(fPID > 0){//parent of 2nd child
        printf("in parent of 2nd childn");
        dup2(fd[1], 1);
                execvp(command, argv);//needs error checking
                printf("mysh: %s: command not foundn", argv[0]);
            exit(EXIT_FAILURE);
    }
    if(PID == -1){
                printf("ERROR:n");
                switch (errno){
                    case EAGAIN:
                    printf("Cannot fork process: System Process Limit Reachedn");
                case ENOMEM:
                    printf("Cannot fork process: Out of memoryn");
                }
                return 1;
    }
        }
        if(PID > 0){//parent
            wait(PID, 0, 0);
    printf("in outer parentn");
        }
        if(PID == -1){
            printf("ERROR:n");
            switch (errno){
                case EAGAIN:
                printf("Cannot fork process: System Process Limit Reachedn");
            case ENOMEM:
                printf("Cannot fork process: Out of memoryn");
            }
            return 1;
        }
}

最新更新