带管道的多个进程,意外的变量变化?
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
变量发生了变化(在同一范围内),因此它甚至没有进入循环。
我还观察到了更多的东西;
- 当将输出重定向到某个文件时,数据看起来像是我的程序的 %10 写在那里。
- 如果我为矩阵提供较小的值,例如 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_x
和third_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
的值超出了第一个维度的索引范围。由于您在数组外写入,因此导致了未定义的行为。
循环应该都从 0
到 third_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。在矩阵中,我认为矩阵的哪一部分产生哪个结果很重要,并且这种结构将使这些信息保持相关。
通过以这种方式组织数据,您可以消除重复代码的诱惑,因为数组上的循环更容易。更少的代码意味着更少的错误,因此您可以更快地完成作业。
我知道这听起来不真实 "unexpected variable change." 因为我找不到问题所以我使用了那个标题...
首先,这是我的作业。作业是从文件中读取两个矩阵,然后创建 4 个 child 进程,parent 将(通过管道)将矩阵的四分之一部分发送到 child 进程。 Child 进程将在之后进行计算,他们会将计算出的索引发送回 parent 进程(再次通过管道。尝试在此处实现双向管道。)因此 parent 会将计算出的值打印到标准输出和 return。
目前我所做的是从文件中读取这些矩阵,创建 3 个进程(逐步进行),将 1/4 的矩阵发送到每 3 个进程并尝试检查我是否成功。
问题是 "generally" 我看到 third_start
变量发生了变化(在同一范围内),因此它甚至没有进入循环。
我还观察到了更多的东西;
- 当将输出重定向到某个文件时,数据看起来像是我的程序的 %10 写在那里。
- 如果我为矩阵提供较小的值,例如 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_x
和third_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
的值超出了第一个维度的索引范围。由于您在数组外写入,因此导致了未定义的行为。
循环应该都从 0
到 third_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。在矩阵中,我认为矩阵的哪一部分产生哪个结果很重要,并且这种结构将使这些信息保持相关。
通过以这种方式组织数据,您可以消除重复代码的诱惑,因为数组上的循环更容易。更少的代码意味着更少的错误,因此您可以更快地完成作业。