带管道的多个进程,意外的变量变化?

Multiple processes with pipe, unexpected variable change?

我知道这听起来不真实 "unexpected variable change." 因为我找不到问题所以我使用了那个标题...

首先,这是我的作业。作业是从文件中读取两个矩阵,然后创建 4 个 child 进程,parent 将(通过管道)将矩阵的四分之一部分发送到 child 进程。 Child 进程将在之后进行计算,他们会将计算出的索引发送回 parent 进程(再次通过管道。尝试在此处实现双向管道。)因此 parent 会将计算出的值打印到标准输出和 return。

目前我所做的是从文件中读取这些矩阵,创建 3 个进程(逐步进行),将 1/4 的矩阵发送到每 3 个进程并尝试检查我是否成功。

问题是 "generally" 我看到 third_start 变量发生了变化(在同一范围内),因此它甚至没有进入循环。

我还观察到了更多的东西;

  1. 当将输出重定向到某个文件时,数据看起来像是我的程序的 %10 写在那里。
  2. 如果我为矩阵提供较小的值,例如 4x4 矩阵。 third_start 的问题不会发生。

我确定我在做一些愚蠢的事情。

这是我的代码的相关部分。 (有点乱,不是我发作业的方式。。请忽略矩阵的计算。)

int pipe_fds[2]; //first pipe
int pipe_fds2[2];//second pipe
int pipe_fds3[2];//third pipe
int pipe_fds4[2];//fourth pipe
int pip_ret, pip_ret2, pip_ret3, pip_ret4;

int pid2,pid3,pid4,pid5; //assumed p1 is parent and 2,3,4,5 are child processes.
int single_x; //store single_x val;
int single_y;
pip_ret = pipe(pipe_fds);
pid2 = fork();
if(pip_ret == -1)
{
    fprintf(stderr, "%s\n", "Unable to create pipe\n");
    exit(1);
}

else if(pid2 == 0)
{
    if (close(pipe_fds[1]) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }


    int first_quarter_x[_pow(2, n) / 2][_pow(2, n) / 2];
    int first_quarter_y[_pow(2, n) / 2][_pow(2, n) / 2];
    for(i = 0 ; i <  _pow(2, n) / 2 ; ++i)
    {
        for(j = 0 ; j < _pow(2, n) / 2; ++j)
        {
            if(read(pipe_fds[0], &single_x, sizeof(single_x)) <= 0)
            {
                perror("read failed ");
                exit(EXIT_FAILURE);
            }
            first_quarter_x[i][j] = single_x;


            if(read(pipe_fds[0], &single_y, sizeof(single_y)) <= 0)
            {
                perror("read failed ");
                exit(EXIT_FAILURE);
            }
            first_quarter_y[i][j] = single_y;
            fprintf(stderr,"(2)Child with pid %d received value %d\n",getpid(), single_x);
            fprintf(stderr,"(2)Child with pid %d received value %d\n",getpid(), single_y);
        }

    }




    for(i = 0 ; i <  _pow(2, n) / 2 ; ++i)
    {
        for(j = 0 ; j < _pow(2, n) / 2; ++j)
        {
            if(matrixA[i][j] == first_quarter_x[i][j])
            {
                fprintf(stderr,"Good2a\n" );
            }
            else
            {
                fprintf(stderr,"Bad2a.\n" );
            }
        }
        fprintf(stderr,"\n" );
    }

    for(i = 0 ; i <  _pow(2, n) / 2 ; ++i)
    {
        for(j = 0 ; j < _pow(2, n) / 2; ++j)
        {
            if(matrixB[i][j] == first_quarter_y[i][j])
            {
                printf("Good2b\n" );
            }
            else
            {
                printf("Bad2b.\n" );
            }
        }
        fprintf(stderr,"\n" );
    }
    exit(EXIT_SUCCESS);

}


pip_ret2 = pipe(pipe_fds2);
pid3 = fork();




if(pip_ret2 == -1)
{
    fprintf(stderr, "%s\n", "Unable to create pipe for 3.process\n");
    exit(1);
}

else if(pid3 == 0)
{

    if (close(pipe_fds2[1]) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }
    int second_start = _pow(2, n) / 2;
    int second_quarter_x[_pow(2, n) / 2][_pow(2, n) / 2];
    int second_quarter_y[_pow(2, n) / 2][_pow(2, n) / 2];
    for(i = 0 ; i <  _pow(2, n) / 2 ; ++i)
    {
        for(j = second_start ; j < _pow(2, n); ++j)
        {
            if(read(pipe_fds2[0], &single_x, sizeof(single_x)) <= 0)
            {
                perror("read failed ");
                exit(EXIT_FAILURE);
            }
            second_quarter_x[i][j] = single_x;

            if(read(pipe_fds2[0], &single_y, sizeof(single_y)) <= 0)
            {
                perror("read failed ");
                exit(EXIT_FAILURE);
            }
            second_quarter_y[i][j] = single_y;

            fprintf(stderr,"(3)Child with pid %d received value %d\n",getpid(), single_x);
            fprintf(stderr,"(3)Child with pid %d received value %d\n",getpid(), single_y);
        }
    }




    for(i = 0 ; i <  _pow(2, n) / 2 ; ++i)
    {
        for(j = second_start ; j < _pow(2, n) ; ++j)
        {
            if(second_quarter_x[i][j] == matrixA[i][j])
            {
                fprintf(stderr,"Good3a \n" );
            }
            else
            {
                fprintf(stderr,"Bad3a\n" );
            }
        }
        fprintf(stderr,"\n" );
    }

    for(i = 0 ; i <  _pow(2, n) / 2 ; ++i)
    {
        for(j = second_start ; j < _pow(2, n) ; ++j)
        {
            if(second_quarter_y[i][j] == matrixB[i][j])
            {
                fprintf(stderr,"Good3b \n" );
            }
            else
            {
                fprintf(stderr,"Bad3b\n" );
            }
        }
        fprintf(stderr,"\n" );
    }

    exit(EXIT_SUCCESS);
}



pip_ret3 = pipe(pipe_fds3);
pid4 = fork();




if(pip_ret3 == -1)
{
    fprintf(stderr, "%s\n", "Unable to create pipe for 4.process\n");
    exit(1);
}

else if(pid4 == 0)
{
    if (close(pipe_fds3[1]) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }
    int third_start = _pow(2, n) / 2;
    printf("THIRD START IS %d\n",third_start ); //here it prints normal.
    int third_quarter_x[_pow(2, n) / 2][_pow(2, n) / 2];
    int third_quarter_y[_pow(2, n) / 2][_pow(2, n) / 2];
    for(i = third_start ; i <  _pow(2, n) ; ++i)
    {
        for(j = 0 ; j < _pow(2, n) / 2; ++j)
        {
            if(read(pipe_fds3[0], &single_x, sizeof(single_x)) <= 0)
            {
                perror("read failed ");
                exit(EXIT_FAILURE);
            }
            third_quarter_x[i][j] = single_x;

            if(read(pipe_fds3[0], &single_y, sizeof(single_y)) <= 0)
            {
                perror("read failed ");
                exit(EXIT_FAILURE);
            }
            third_quarter_y[i][j] = single_y;

            fprintf(stderr,"(4)Child with pid %d received value %d\n",getpid(), single_x);
            fprintf(stderr,"(4)Child with pid %d received value %d\n",getpid(), single_y);
        }
    }
    printf("THIRD START IS %d\n",third_start ); //then it prints something anormal...

    for(i = third_start ; i <  _pow(2, n) ; ++i)
    {
        for(j = 0 ; j < _pow(2, n) / 2; ++j)
        {
            if(third_quarter_x[i][j] == matrixA[i][j])
            {
                fprintf(stderr,"Good4a \n" );
            }
            else
            {
                fprintf(stderr,"Bad4a\n" );
            }
        }
        printf("\n" );
    }

    for(i = third_start ; i <  _pow(2, n) ; ++i)
    {
        for(j = 0 ; j < _pow(2, n) / 2; ++j)
        {
            if(third_quarter_x[i][j] == matrixB[i][j])
            {
                fprintf(stderr,"Good4b \n" );
            }
            else
            {
                fprintf(stderr,"Bad4b\n" );
            }
        }
        fprintf(stderr,"\n" );
    }

    exit(EXIT_SUCCESS);
}





        //parent start
    if (close(pipe_fds[0]) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }
    fprintf(stderr,"First quarter beginning \n");
    for(i = 0 ; i <  _pow(2, n) / 2 ; ++i)
    {
        for(j = 0 ; j < _pow(2, n) / 2; ++j)
        {
            single_x = matrixA[i][j];
            single_y = matrixB[i][j];
            write(pipe_fds[1], &single_x, sizeof(single_x));
            write(pipe_fds[1], &single_y, sizeof(single_y));
            fprintf(stderr,"Parent with pid %d sent value to 2 %d\n",getpid(), single_x);
            fprintf(stderr,"Parent with pid %d sent value to 2 %d\n",getpid(), single_y);
        }

    }
    wait(NULL);
    fprintf(stderr,"First quarter end\n \n");




    fprintf(stderr,"Second quarter beginning\n");

    if (close(pipe_fds2[0]) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }
    int sec = _pow(2,n) / 2;

    for(i = 0 ; i <  _pow(2, n) / 2 ; ++i)
    {
        for(j = sec ; j < _pow(2, n); ++j)
        {
            single_x = matrixA[i][j];
            single_y = matrixB[i][j];
            write(pipe_fds2[1], &single_x, sizeof(single_x));
            write(pipe_fds2[1], &single_y, sizeof(single_y));
            fprintf(stderr,"Parent with pid %d sent value to 3 %d\n",getpid(), single_x);
            fprintf(stderr,"Parent with pid %d sent value to 3 %d\n",getpid(), single_y);
        }

    }
    wait(NULL);
    fprintf(stderr,"Second quarter end\n");



    fprintf(stderr,"Third quarter beginning\n");

    if (close(pipe_fds3[0]) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }
    int third = _pow(2,n) / 2;

    for(i = third ; i <  _pow(2, n) ; ++i)
    {
        for(j = 0 ; j < _pow(2, n) / 2; ++j)
        {
            single_x = matrixA[i][j];
            single_y = matrixB[i][j];
            write(pipe_fds3[1], &single_x, sizeof(single_x));
            write(pipe_fds3[1], &single_y, sizeof(single_y));
            fprintf(stderr,"Parent with pid %d sent value to 4 %d\n",getpid(), single_x);
            fprintf(stderr,"Parent with pid %d sent value to 4 %d\n",getpid(), single_y);
        }

    }
    wait(NULL);
    fprintf(stderr,"Third quarter end\n");

您正在访问数组外部。

    int third_start = _pow(2, n) / 2;
    printf("THIRD START IS %d\n",third_start ); //here it prints normal.
    int third_quarter_x[_pow(2, n) / 2][_pow(2, n) / 2];
    int third_quarter_y[_pow(2, n) / 2][_pow(2, n) / 2];

third_quarter_xthird_quarter_y两个维度的索引从0third_start-1。但是你有以下循环:

    for(i = third_start ; i <  _pow(2, n) ; ++i)
    {
        for(j = 0 ; j < _pow(2, n) / 2; ++j)
        {

i 的值超出了第一个维度的索引范围。由于您在数组外写入,因此导致了未定义的行为。

循环应该都从 0third_start

您在之前使用 second_start 的过程中遇到了类似的问题,只是它是在 j 循环中进行的。

int pipe_fds2[2];//second pipe

间接帮助:编号变量几乎总是更好地表示为数组。你可能想要一个结构数组

struct child_t {
    int datapipe[2], resultpipe[2];
    pid_t pid;
    int result;
} children[4];

现在您可以遍历数组,并为每个元素调用 pipe 和 fork。每个 child 只处理它的管道,但 parent 可以遍历所有 children。在矩阵中,我认为矩阵的哪一部分产生哪个结果很重要,并且这种结构将使这些信息保持相关。

通过以这种方式组织数据,您可以消除重复代码的诱惑,因为数组上的循环更容易。更少的代码意味着更少的错误,因此您可以更快地完成作业。