Как shmget и shmat двойной массив в C? - PullRequest
1 голос
/ 19 ноября 2010

Я знаю, что двумерный массив может быть странным в C, а с malloc я бы сделал что-то вроде этого:

/* This is your 2D array. */
double** matrix;
/* The size dimensions of your 2D array. */
int numRows, numCols;
/* Used as indexes as in matrix[x][y]; */
int x, y; 
/*
 * Get values into numRows and numCols somehow.
 */


/* Allocate pointer memory for the first dimension of a matrix[][]; */
matrix = (double **) malloc(numCols * sizeof(double *));
if(NULL == matrix){free(matrix); printf("Memory allocation failed while allocating for matrix[].\n"); exit(-1);}

/* Allocate integer memory for the second dimension of a matrix[][]; */
for(x = 0; x < numCols; x++)
{
    matrix[x] = (double *) malloc(numRows * sizeof(double));
    if(NULL == matrix[x]){
        free(matrix[x]); printf("Memory allocation failed while allocating for matrix[x][].\n");
         exit(-1);
    }
}

и инициализировать, с 2 форсами, массив. Теперь я хочу выделить пространство в разделяемой памяти для массива **, но я не знаю, смогу ли я сделать это:

shmid2 = shmget(IPC_PRIVATE, numCols * sizeof (int*), IPC_CREAT | 0700);
my_array = (double**) shmat(shmid2, NULL, 0);

и затем инициализируйте его. Это правильно. Если нет, то как я могу сделать это правильно?

Заранее спасибо

Ответы [ 3 ]

2 голосов
/ 19 ноября 2010

Вы можете сделать это с одним непрерывным сегментом разделяемой памяти. Хитрость в том, что сами значения double находятся в общей памяти, но ваши указатели строк double * могут быть просто обычной malloc памятью, поскольку они являются просто индексом в общей памяти:

double *matrix_data;
double **matrix;
int x;

shmid2 = shmget(IPC_PRIVATE, numRows * numCols * sizeof matrix_data[0], IPC_CREAT | 0700);
matrix_data = shmat(shmid2, NULL, 0);

matrix = malloc(numCols * sizeof matrix[0]);
for(x = 0; x < numCols; x++)
{
    matrix[x] = matrix_data + x * numRows;
}

(Обратите внимание, что это выделяет индекс в мажорном порядке столбца, как это делает ваш код, что необычно для Си - мажорный ряд более распространен).

Отдельные программы, совместно использующие сегмент общей памяти, присваивают каждому свой собственный индекс matrix, используя malloc - только фактический массив является общим.

Кстати, вы можете использовать тот же метод для не разделяемого массива, заменив вызов совместно используемой памяти простым malloc(). Это позволяет вам использовать одно выделение для всего массива плюс одно для индекса, тогда как ваш код имеет одно выделение на столбец .

0 голосов
/ 19 ноября 2010

Я сделал это!Я приведу и пример со структурой, отличной от двойного массива, но вы получите точку.

Итак, в основном я хочу выделить ** pixel, pixel_data (член структуры image_struct, здесь создается как image)в сегменте совместно используемой памяти.

    shmid2 = shmget(IPC_PRIVATE, image->width * sizeof (pixel*), IPC_CREAT | 0700);
    image->pixel_data = (pixel**) shmat(shmid2, NULL, 0);

    /* Allocate integer memory for the second dimension of **pixel_data; */
    for (i = 0; i < image->width; i++) {
        shmPixelId = shmget(IPC_PRIVATE, image->height * sizeof (pixel), IPC_CREAT | 0700);
        image->pixel_data[i] = (pixel *) shmat(shmPixelId, NULL, 0);
        if ( image->pixel_data[i]== NULL) {
            shmdt(image->pixel_data[i]);
            printf("Sh_Memory allocation failed while allocating for pixel_data[i][].\n");
            exit(-1);
        }
    }

Мои структуры:

typedef struct pixel_t {
    byte red;
    byte green;
    byte blue;
}pixel;

typedef struct {
    int width;
    int height;
    pixel **pixel_data;
} image_struct;

Я следую тому же коду, который я использовал для размещения в памяти размерного массива, но вместо этого я использовал общую память.

0 голосов
/ 19 ноября 2010

Я бы так не поступил, даже с malloc из-за фрагментации памяти, когда массив стал большим. И с shmget вы получите проблему также с fd (используется один fd на shmget).

Я бы порекомендовал сделать это таким образом (без компиляции, так как нет компилятора C близко)

double* matrix = malloc( sizeof(double)*numrows*numcols);

double value = matrix[actrow*numrows+actcol];

free ( matrix);

Вы должны помнить numrows по всему вашему приложению, но таким образом оно намного более чисто со стороны памяти. Кроме того, теперь это один большой кусок, и вы можете сделать то же самое с shmget / shmat.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...