【问题标题】:Multiple processes with pipe, unexpected variable change?带有管道的多个进程,意外的变量更改?
【发布时间】:2020-08-03 10:29:30
【问题描述】:

我知道这听起来不真实的“意外的变量变化”。由于我无法发现问题,所以我使用了该标题...

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

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

问题是“通常”发生的情况是我看到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");

【问题讨论】:

  • 这可能是内存损坏的情况。申请valgrind
  • 可能与问题无关,但你应该检查pipe()是否在你fork之前失败。否则,父母和孩子都会做这个检查。
  • 你在所有子进程中有很多重复的代码,你应该把它放到一个函数中。
  • 仅供参考:_pow(2, n) / 2_pow(2, n-1) 相同
  • @Barmar 1-)确定我应该在创建管道后检查返回值。 2-)我知道那里很乱,肯定会清理那里。 3-)如果我可怜的 _pow 函数不知道如何计算 2^(-1) 怎么办 :)

标签: c process pipe fork ipc


【解决方案1】:

您正在访问数组之外​​。

    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两个维度的索引从0变为third_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 循环中进行的。

【讨论】:

  • 当然,谢谢!!希望我在那里遇到段错误:
  • 局部变量的大小是有限的,所以如果数组可以变大,你应该使用malloc()
【解决方案2】:

int pipe_fds2[2];//second pipe

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

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

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

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

【讨论】:

  • 是的,更结构化、更优雅的方式。谢谢你的建议:)
猜你喜欢
  • 1970-01-01
  • 2018-05-03
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多