并行过程场景实现停留在等待输入上

时间:2016-03-28 08:03:33

标签: c linux operating-system pipe fork

我正在努力实现这种情况:

parallel process scenario

其中ls -lcat /etc/group进程并行运行,tr /a-z/ /A-Z/从中获取组合输入。然后将它们的大写版本转移到cat -ngrep Z(它们也应该并行运行)。 cat -ngrep Z应输出到stdout。

所以在stdoutput中,

(ls -l ; cat /etc/group) | tr /a-z/ /A-Z/ | cat -n

(ls -l ; cat /etc/group) | tr /a-z/ /A-Z/ | grep A

应该打印出来。

我写了这个程序来实现我的目标:

#include<stdio.h>
#include<unistd.h>
#include<wait.h>

int main()
{
    int    dummy, i;
    size_t size = 0;
    int    pipe1[2];
    int    pipe2[2];
    int    pipe3[2];
    char* lsargs0[] = {"/bin/ls", "-l", NULL};
    char* lsargs1[] = {"cat", "/etc/group", NULL};
    char* lsargs2[] = {"tr", "/a-z/", "/A-Z/", NULL};
    char* lsargs3[] = {"cat", "-n", NULL};
    char* lsargs4[] = {"grep", "A", NULL};
    char** am[]     = {lsargs0, lsargs1, lsargs2, lsargs3, lsargs4};
    char buf[4096];

    pipe(pipe1);
    pipe(pipe2);
    pipe(pipe3);

    for ( i = 0 ; i < 5 ; i++ )
    {
        pid_t pid = fork();

        if ( pid == 0 )
        {
            if ( i == 0 || i == 1 ) // ls -l & cat
            {
                // 0 -> stdin, 1 -> pipe write end
                close(pipe2[0]);
                close(pipe2[1]);

                close(pipe3[0]);
                close(pipe3[1]);

                close(pipe1[0]);
                dup2(pipe1[1], 1);
                close(pipe1[1]);

                execvp(am[i][0], am[i]);
            }
            else if ( i == 2 ) //TR AZ AZ
            {
                int extraPipe[2];
                pipe(extraPipe);

                int forkMaster = fork();

                if ( forkMaster != 0 )
                {
                    printf("TR az AZ fork parent\n");
                    //parent
                    close(pipe2[0]);
                    close(pipe2[1]);

                    close(pipe3[0]);
                    close(pipe3[1]);

                    close(pipe1[1]);
                    dup2(pipe1[0], 0);
                    close(pipe1[0]);

                    close(extraPipe[0]);
                    dup2(extraPipe[1], 1);
                    close(extraPipe[1]);

                    //waitpid(forkMaster, &dummy, WNOHANG);
                    //wait(&dummy);

                    execvp(am[i][0], am[i]);
                }
                else
                {
                    printf("TR az AZ child\n");
                    //child
                    read(extraPipe[0], buf, 4095);
                    //printf("%s\n", buf);

                    write(pipe2[1], buf, size);
                    write(pipe3[1], buf, size);
                    close(pipe1[1]);
                    close(pipe1[0]);

                    close(extraPipe[0]);
                    close(extraPipe[1]);

                    close(pipe2[0]);
                    close(pipe2[1]);

                    close(pipe3[0]);
                    close(pipe3[1]);
                    break;
                }
            }
            else if ( i == 3 ) // cat -n
            {
                close(pipe1[0]);
                close(pipe1[1]);

                close(pipe3[0]);
                close(pipe3[1]);

                close(pipe2[1]);
                dup2(pipe2[0], 0);
                close(pipe2[0]);

                execvp(am[i][0], am[i]);
            }
            else if ( i == 4 ) //grep Z
            {
                close(pipe1[0]);
                close(pipe1[1]);

                close(pipe2[0]);
                close(pipe2[1]);

                close(pipe3[1]);
                dup2(pipe3[0], 0);
                close(pipe3[0]);

                execvp(am[i][0], am[i]);
            }
            break;
        }
            //DON'T FORGET TO CLOSE PIPES ON PARENT
        else if ( i == 4 )
        {
            close(pipe1[0]);
            close(pipe1[1]);

            close(pipe2[0]);
            close(pipe2[1]);

            close(pipe3[0]);
            close(pipe3[1]);
        }
    }
    for ( i = 0 ; i < 5 ; i++ )
    {
        wait(&dummy);
    }
    return 0;
}

但该计划停留在read(extraPipe[0], buf, 4096);行。我究竟做错了什么?你能救我吗?

1 个答案:

答案 0 :(得分:0)

两个进程i == 2仍在等待彼此。我向后移动了一些close(),它似乎正常工作。复制过程还需要loopexit(0);而不是break;

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wait.h>

int main()
{
    int    dummy, i;
    size_t size = 0;
    int    pipe1[2];
    int    pipe2[2];
    int    pipe3[2];
    char* lsargs0[] = {"/bin/ls", "-l", NULL};
    char* lsargs1[] = {"cat", "/etc/group", NULL};
    char* lsargs2[] = {"tr", "/a-z/", "/A-Z/", NULL};
    char* lsargs3[] = {"cat", "-n", NULL};
    char* lsargs4[] = {"grep", "A", NULL};
    char** am[]     = {lsargs0, lsargs1, lsargs2, lsargs3, lsargs4};
    char buf[4096];

    pipe(pipe1);
    pipe(pipe2);
    pipe(pipe3);

    for ( i = 0 ; i < 5 ; i++ )
    {
        pid_t pid = fork();
        /*if (pid > 0)
            printf("pid %d = %ld\n", i, (long) pid);*/

        if ( pid == 0 )
        {
            if ( i == 0 || i == 1 ) // ls -l & cat
            {
                // 0 -> stdin, 1 -> pipe write end
                close(pipe2[0]);
                close(pipe2[1]);

                close(pipe3[0]);
                close(pipe3[1]);

                close(pipe1[0]);
                dup2(pipe1[1], 1);
                close(pipe1[1]);

                execvp(am[i][0], am[i]);
            }
            else if ( i == 2 ) //TR AZ AZ
            {
                int extraPipe[2];
                pipe(extraPipe);

                int forkMaster = fork();

                if ( forkMaster != 0 )
                {
                    printf("TR az AZ fork parent\n");
                    //parent
                    close(pipe2[0]);
                    close(pipe2[1]);

                    close(pipe3[0]);
                    close(pipe3[1]);

                    close(pipe1[1]);
                    dup2(pipe1[0], 0);
                    close(pipe1[0]);

                    close(extraPipe[0]);
                    dup2(extraPipe[1], 1);
                    close(extraPipe[1]);

                    //waitpid(forkMaster, &dummy, WNOHANG);
                    //wait(&dummy);

                    execvp(am[i][0], am[i]);
                }
                else
                {
                    printf("TR az AZ child\n");
                    //child
                    close(pipe1[1]);
                    close(pipe1[0]);
                    close(pipe2[0]);
                    close(pipe3[0]);
                    fprintf(stderr, "Line %d\n", __LINE__);
                    close(extraPipe[1]);
                    do
                    {
                        size = read(extraPipe[0], buf, 4095);
                        if (size > 0)
                        {
                            write(pipe2[1], buf, size);
                            write(pipe3[1], buf, size);
                        }
                    } while (size > 0);
                    fprintf(stderr, "Line %d\n", __LINE__);
                    //printf("%s\n", buf);


                    close(extraPipe[0]);
                    close(pipe2[1]);
                    close(pipe3[1]);

                    exit(0);

                }
            }
            else if ( i == 3 ) // cat -n
            {
                close(pipe1[0]);
                close(pipe1[1]);

                close(pipe3[0]);
                close(pipe3[1]);

                close(pipe2[1]);
                dup2(pipe2[0], 0);
                close(pipe2[0]);

                execvp(am[i][0], am[i]);
            }
            else if ( i == 4 ) //grep A
            {
                close(pipe1[0]);
                close(pipe1[1]);

                close(pipe2[0]);
                close(pipe2[1]);

                close(pipe3[1]);
                dup2(pipe3[0], 0);
                close(pipe3[0]);

                execvp(am[i][0], am[i]);
            }
            break;
        }
            //DON'T FORGET TO CLOSE PIPES ON PARENT
        else if ( i == 4 )
        {
            close(pipe1[0]);
            close(pipe1[1]);

            close(pipe2[0]);
            close(pipe2[1]);

            close(pipe3[0]);
            close(pipe3[1]);
        }
    }
    for ( i = 0 ; i < 5 ; i++ )
    {
        wait(&dummy);
    }
    return 0;
}