使用 mmap 分配双二维数组

Using mmap to allocate double 2D array

我正在尝试使用 mmap create/access twi 不同的 (N+2)*(N+2) 双精度二维数组,以便多个线程可以查看自己的部分并更改它, 应用更改以便所有其他人都能看到。这是我拥有的:

int main(int argc, char *argv[]) {
    int N = atoi(argv[1]);
    int numProcs = atoi(argv[2]);

    int ARRAY_SIZE = (N+2)*(N+2)*sizeof(double);

    double **grid = (double **) mmap(NULL, ARRAY_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
    if (grid == MAP_FAILED) {
        printf("Error mmapping grid\n");
    }
    double **newGrid = (double **) mmap(NULL, ARRAY_SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
    if (newGrid == MAP_FAILED) {
        printf("Error mmapping grid\n");
    }

当我 运行 它或尝试访问其中的任何内容时,我遇到了分段错误。我也尝试分配内存,使用:

for(i = 0; i < N+2; i++) {
    for(j = 0; j < N+2; j++) {
        grid[i][j] = malloc(sizeof(double));
    }
}

for(i = 0; i < N+2; i++) {
    for(j = 0; j < N+2; j++) {
        newGrid[i][j] = malloc(sizeof(double));
    }
}

但我遇到了:错误:从不兼容的类型 'void *' 分配给 'double' newGrid[i][j] = malloc(sizeof(double));

我想我在这里遗漏了一些关于 mmap 工作原理的东西,有人能指出我正确的方向吗?

数组或数组的数组是连续的内存区域。使用指向指针的指针的“二维数组”是连续的。

让我们看一些 "images" 进行比较:

正确的数组数组在内存中看起来像这样:

+--------------+--------------+-----+----------------+--------------+-----+------------------+
| matrix[0][0] | matrix[0][1] | ... | matrix[0][N-1] | matrix[1][0] | ... | matrix[M-1][N-1] |
+--------------+--------------+-----+----------------+--------------+-----+------------------+

另一方面,使用指针到指针的矩阵看起来像这样:

+-----------+-----------+-----------+-----+
| matrix[0] | matrix[1] | matrix[2] | ... |
+-----------+-----------+-----------+-----+
 |           |           |
 |           |           V
 |           |           +--------------+--------------+-----+
 |           |           | matrix[2][0] | matrix[2][1] | ... |
 |           |           +--------------+--------------+-----+
 |           |
 |           V
 |           +--------------+--------------+-----+
 |           | matrix[1][0] | matrix[1][1] | ... |
 |           +--------------+--------------+-----+
 |
 V
 +--------------+--------------+-----+
 | matrix[0][0] | matrix[0][1] | ... |
 +--------------+--------------+-----+

如您所见,它们的内存布局完全不同,这就是为什么您不能将一个用作另一个的原因。

如果 N 是一个编译时常量,或者如果您的编译器支持可变长度数组 (VLA),那么您可以简单地执行以下操作:

double (*grid)[N+2] = (double (*)[N+2]) mmap(NULL, ARRAY_SIZE, ...

grid[4][5] = 2.0;  // setting an element

如果N不是常量,你的编译器不支持VLA,那么你需要手动偏移:

double *grid = (double *) mmap(NULL, ARRAY_SIZE, ...

grid[4 * (N + 2) + 5] = 2.0;  // setting the same element using manual offsets