简体   繁体   English

等待输入的并行流程方案实现

[英]A parallel process scenario realization stuck on waiting input

I am trying to realize this scenario: 我正在尝试实现这种情况:

parallel process scenario 并行流程场景

where ls -l and cat /etc/group processes run parallel, and tr /az/ /AZ/ takes combined input from them. 其中ls -lcat /etc/group进程并行运行,而tr /az/ /AZ/从中获取组合的输入。 And then transfers uppercase version of them to either cat -n and grep Z (they also should run parallel). 然后将它们的大写版本传输到cat -ngrep Z (它们也应该并行运行)。 cat -n and grep Z should output to stdout. cat -ngrep Z应该输出到stdout。

So in the stdoutput, 因此在stdoutput中,

(ls -l ; cat /etc/group) | tr /az/ /AZ/ | cat -n

(ls -l ; cat /etc/group) | tr /az/ /AZ/ | grep A

should be printed. 应该打印出来。

I've written this program to achieve my goal: 我已经编写了此程序来实现我的目标:

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

But the program stucks on read(extraPipe[0], buf, 4096); 但是程序卡在read(extraPipe[0], buf, 4096); line. 线。 What am I doing wrong? 我究竟做错了什么? Can you help me? 你能帮助我吗?

The two processes i == 2 are still waiting for each other. i == 2的两个进程仍在互相等待。 I moved backward some close() and it seems to work properly. 我向后移了一些close() ,它似乎正常工作。 Also need a loop for the duplicating process and an exit(0); 还需要一个用于复制过程的loop和一个exit(0); rather than a break; 而不是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;
}

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

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