Как поделиться переменной char ** с помощью общей памяти

Я использую общую память для связи между двумя процессами. Я использую char** для подключения к общему адресному пространству. Проблема в том, что когда я заполняю данные о производителе, а затем присоединяю потребителя к адресному пространству, никакие данные не передаются. Я просто получаю нулевые значения

Это фрагмент моего продюсера

// create shared memory
shm_handle = shmget(key, BUFF_SIZE * PAGE_SIZE, IPC_CREAT | 0644);
printf("\nhandle is %d\n", shm_handle);
// valid handle?
if (shm_handle == -1) {
  printf("shared memory creation failed\n");
  exit(0);
}
// attach to shared block, see man pages for detail
buf = (char**) shmat(shm_handle, 0, 0);
if (buf == (char **) -1) {
  printf("Shared memory attach failed");
  exit(0);
}
int a = 0;
buf = malloc(sizeof(char*) * BUFF_SIZE);
for (a = 0; a < BUFF_SIZE; a++) {
  buf[a] = malloc(sizeof(char) * PAGE_SIZE);
}

и потребитель

// create shared memory
shm_handle = shmget(key, BUFF_SIZE * PAGE_SIZE, IPC_CREAT | 0644);
printf("handle is %d", shm_handle);
// valid handle?
if (shm_handle == -1) {
  printf("shared memory creation failed\n");
  exit(0);
}
char ** buft;
int a = 0;
// attach to shared block
buf = (char**) shmat(shm_handle, 0, 0);
if (buf == (char **) -1) {
  printf("Shared memory attach failed");
  exit(0);
}
buf = malloc(sizeof(char*) * BUFF_SIZE);
buft = malloc(sizeof(char*) * PAGE_SIZE);
for (a = 0; a < BUFF_SIZE; a++) {
  buf[a] = malloc(sizeof(char) * PAGE_SIZE);
  buft[a] = malloc(sizeof(char) * PAGE_SIZE);
}
printf("%s", buf[0]);

person Yanki Twizzy    schedule 14.03.2014    source источник
comment
Я не думаю, что ты так делаешь. Разве malloc не стирает и не перезаписывает ваш адрес в общей памяти?   -  person Jiminion    schedule 14.03.2014
comment
buf = (char**) shmat(...); buf = malloc(...); вы выбрасываете то, что дал вам шмат, и заменяете скучным старым неразделяемым распределением...   -  person Mat    schedule 14.03.2014
comment
Я поставил malloc перед подключением к общей памяти, но он все еще был нулевым.   -  person Yanki Twizzy    schedule 14.03.2014
comment
Что сказал Мэт! Совместно используемая память — это, как правило, просто указатель, а не все, что вы можете использовать для извлечения и освобождения, если только вы не хотите писать все эти вещи самостоятельно.   -  person Jiminion    schedule 14.03.2014
comment
Общая память возвращается shmat. malloc вообще не должен использоваться в этом случае.   -  person Marian    schedule 14.03.2014
comment
Имеют ли потребитель и производитель одинаковые ключи? И должны ли они оба создавать?   -  person Jiminion    schedule 14.03.2014
comment
@Marian Если я не использую malloc, я не могу получить доступ к своему символу **, как к двумерному массиву. Я помещаю в него вещи, как если бы это был 2D-массив.   -  person Yanki Twizzy    schedule 14.03.2014
comment
@Jim Да, они оба должны иметь возможность создавать, чтобы потребитель или производитель могли быть запущены первыми. Могу ли я иметь указатель на (указатель на указатель), чтобы общая память была просто указателем?   -  person Yanki Twizzy    schedule 14.03.2014


Ответы (2)


Ваш код не помещает ваши строки в общую память. Он помещает их в кучу, как всегда делает malloc, потому что вы делаете:

buf = (char**) shmat(shm_handle, 0, 0);
...
/* now throw away the value of `buf` you got from shm */
buf = malloc(sizeof(char*) * BUFF_SIZE);

Что вам нужно будет сделать, это:

  1. Не используйте кучу для размещения вещей, которые вы хотите в общей памяти

  2. Вместо этого захватите достаточно большой объем разделяемой памяти для всего, затем скопируйте его, запись за записью — т.е. разложите в памяти вручную.

person abligh    schedule 14.03.2014

Выделение данных в разделяемой памяти сложно и чревато ошибками, поскольку адреса разделяемой памяти не обязательно одинаковы в каждом процессе. Если вы не предпримете шаги для обеспечения того, чтобы адреса были одинаковыми, вы не сможете хранить указатели в общей памяти, поскольку они не будут указывать на нужное место — вместо этого вам нужно хранить смещения в общей памяти.

После того, как вы вернете часть памяти из shmat, вам нужно самостоятельно управлять распределением в этом пространстве, отслеживая, что используется, а что свободно. В общем случае вам нужно переопределить malloc/free, используя разделяемое пространство, так как система malloc/free всегда работает с неразделяемой памятью кучи. Это нетривиально.

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

person Chris Dodd    schedule 14.03.2014