【问题标题】:A parallel process scenario realization stuck on waiting input一个并行进程场景实现卡在等待输入
【发布时间】:2016-07-15 11:25:32
【问题描述】:

我正在尝试实现这种情况:

parallel process scenario

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

所以在标准输出中,

(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); 行。我究竟做错了什么?你能帮帮我吗?

【问题讨论】:

  • small.c:97:29: error: 'n' may be uninitialized... 您是否编译了您作为示例放置的代码?您需要在发布之前对其进行测试。
  • 我用 gcc 编译成功了。但是对你来说,我移动了导致编译器出错的那一行,你能再试一次吗?
  • 你使用的编译命令是什么?我建议至少-Wall 你会被警告你的变量没有初始化(这会导致未定义的行为)。
  • 我确实使用了-Wall 标志,它现在编译时没有任何警告。你可以看看代码。
  • 现在试图理解,带有 j 变量的 for 循环应该做什么?你要关闭一些文件描述符两次!

标签: c linux operating-system pipe fork


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2016-09-09
    • 2013-05-25
    • 2018-11-19
    • 2018-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-15
    • 1970-01-01
    相关资源
    最近更新 更多