在父母和子女过程之间传播的矩阵数据的差异

时间:2014-03-23 05:37:31

标签: c arrays matrix process pipe

对于我的项目,我需要在进程之间传递矩阵(稍后将在运行时确定各种大小),并对它们执行操作。这将在UNIX系统上执行。

在自学fork()pipe()时,我设法在某些过程之间建立了两个单向管道(一个从父到孩子,反之亦然)。

=============================================== ============

这是我的代码:

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

#define READ_END 0

#define WRITE_END 1

#define MATRIX_N 2


void print_mat(int**, int);


int main(void){
// INITIALIZE
int **w_mat, **r_mat, **return_mat, i, j;
int fd1[2];
int fd2[2];
pid_t pid;

// Allocate memory for respective arrays
w_mat = (int**) malloc(sizeof(int *) * MATRIX_N);

for( i = 0 ; i < MATRIX_N ; i++ ){
    *(w_mat + i) = (int*) malloc (sizeof(int *) * MATRIX_N);
}

r_mat = (int**) malloc(sizeof(int *) * MATRIX_N);

for( i = 0 ; i < MATRIX_N ; i++ ){
    *(r_mat + i) = (int*) malloc (sizeof(int *) * MATRIX_N);
}

return_mat = (int**) malloc(sizeof(int *) * MATRIX_N);

for( i = 0 ; i < MATRIX_N ; i++ ){
    *(return_mat + i) = (int*) malloc (sizeof(int *) * MATRIX_N);
}

// Assign initial values to matrix for writing
w_mat[0][0] = 2;
w_mat[0][1] = 7;
w_mat[1][0] = 12;
w_mat[1][1] = 9;

// Initialize and check pipes respectively
if( pipe(fd1) == -1){
    fprintf(stderr, "Pipe failed");
    return 1;
}

if( pipe(fd2) == -1){
    fprintf(stderr, "Pipe failed");
    return 1;
}

// Fork a child, then check it
pid = fork();

if( pid < 0 ){
    fprintf(stderr, "Fork failed");
}

if( pid > 0 ){ /* PARENT */
    // Close unnecessary pipe ends
    close(fd1[READ_END]);
    close(fd2[WRITE_END]);

    printf("\nMatrix to send to child: ");
    print_mat(w_mat, MATRIX_N);

    // Write to pipe 1, matrix for child, then close pipe
    write(fd1[WRITE_END], w_mat, MATRIX_N * MATRIX_N * sizeof(int*));

    // Wait for child to process values, write, and terminate
    wait(NULL);

    // Read values from pipe 2
    read(fd2[READ_END], return_mat, MATRIX_N * MATRIX_N * sizeof(int*));

    printf("\nDoubled matrix received from child: ");
    print_mat(return_mat, MATRIX_N);

    // Close used pipe ends
    close(fd2[READ_END]);
    close(fd1[WRITE_END]);
}else{ /* CHILD */
    // Close unnecessary pipe ends
    close(fd1[WRITE_END]);
    close(fd2[READ_END]);

    // Read from pipe 1 the matrix from the parent
    read(fd1[READ_END], r_mat, MATRIX_N * MATRIX_N * sizeof(int*));

    printf("\nReceived matrix from parent to double: ");
    print_mat(r_mat, MATRIX_N);

    // Double the values in the matrix from parent
    for( i = 0 ; i < MATRIX_N ; i++ ){
        for( j = 0 ; j < MATRIX_N ; j++){
            r_mat[i][j] = r_mat[i][j] * MATRIX_N;
        }
    }

    printf("\nDoubled matrix to send to parent: ");
    print_mat(r_mat, MATRIX_N);

    // Write to pipe 2, the doubled matrix to be received by parent
    write(fd2[WRITE_END], r_mat, MATRIX_N * MATRIX_N * sizeof(int*));

    // Close used pipe ends
    close(fd2[WRITE_END]);
    close(fd1[READ_END]);
}

// Terminate
return 0;
}

=============================================== ============

运行程序时出现问题:

=============================================== ============

Matrix to send to child: 
| 2 7 |

| 12 9 |

Received matrix from parent to double: 
| 2 7 |

| 12 9 |

Doubled matrix to send to parent: 
| 4 14 |

| 24 18 |

Doubled matrix received from child: 
| 2 7 |

| 12 9 |

=============================================== ============

写入之前的数组是正确的,似乎不知何故在将孩子从孩子写入管道2并在孩子终止后从所述管道读回来的时候;价值回归到了原来的样子。我不相信它可能是进程篡改它,因为每个都有自己的变量数组来存储数据,除了管道之外,实际上没有实例,在我的程序的if语句中,进程直接影响另一个数组 - 据我所知,就是这样。

实际上,是否存在父或子间接影响我不考虑的写入和读取数组的实例?如果是这样,我怎么能控制住这个?如果没有,我到底哪里出错了?我的管道实施本身是否存在缺陷?我真的不确定要找什么。

也;在字段实例的最左边,我的矩阵打印功能是罪魁祸首,这就是:

void print_mat(int** a, int n){

    int i, j;

    for( i = 0 ; i < n ; i++){
        printf("\n| ");
        for( j = 0 ; j < n ; j++){
            printf("%d", a[i][j]);
            if( j != n - 1){
                printf(" ");
            }
        }
        printf(" |\n");
    }
}

1 个答案:

答案 0 :(得分:0)

每个矩阵都是一个指针数组,每个指针都指向一个int数组。因此,用于在父级和子级之间传递矩阵的方法将无法按您希望的方式工作。

你正在做的是在管道上传递四个指针(其中只有前两个有效)。由于子项是父项的副本,这些指针实际上指向父项地址空间中的原始矩阵。因此,父母打印原始矩阵。

您要做的是在管道中传递整数值,并在另一侧重建矩阵。将单个值写入管道需要类似于print_mat函数的代码。在接收方,需要读取这些值并将其存储在阵列中的适当位置。

让我看看我是否可以用一个例子来澄清。如果数组声明为

 int w_mat[2][2];

然后你可以像这样传输整个数组

write(fd1[WRITE_END], w_mat, 2*2 * sizeof(int) );

但事实上数组相当于这个

int *w_mat[2];  
w_mat[0] = malloc( 2 * sizeof(int) ); 
w_mat[1] = malloc( 2 * sizeof(int) );

因此,行

write(fd1[WRITE_END], w_mat, MATRIX_N * MATRIX_N * sizeof(int*));

正在向管道写入四个int *。这有两个原因。

  1. 数组中只有两个指针
  2. 在管道上传递指针与通过管道发送数据不同。