как использовать разделяемую память для связи между двумя процессами - PullRequest
13 голосов
/ 30 августа 2011

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

process1.c

#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
int main ()
{
  int segment_id;
  char* shared_memory[3];
  int segment_size;
  key_t shm_key;
  int i=0;
  const int shared_segment_size = 0x6400;
  /* Allocate a shared memory segment. */
  segment_id = shmget (shm_key, shared_segment_size,
            IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
  /* Attach the shared memory segment. */
  shared_memory[3] = (char*) shmat (segment_id, 0, 0);
  printf ("shared memory attached at address %p\n", shared_memory);
  /* Write a string to the shared memory segment. */
   sprintf(shared_memory[i], "maddy \n");
   sprintf(shared_memory[i+1], "73453916\n");
   sprintf(shared_memory[i+2], "america\n");

  /*calling the other process*/
  system("./process2");

  /* Detach the shared memory segment. */
  shmdt (shared_memory);
  /* Deallocate the shared memory segment.*/
  shmctl (segment_id, IPC_RMID, 0);

  return 0;
}

process2.c

#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
int main ()
{
  int segment_id;
  char* shared_memory[3];
  int segment_size;
  int i=0;
  key_t shm_key;
  const int shared_segment_size = 0x6400;
  /* Allocate a shared memory segment. */
  segment_id = shmget (shm_key, shared_segment_size,
              S_IRUSR | S_IWUSR);
  /* Attach the shared memory segment. */
  shared_memory[3] = (char*) shmat (segment_id, 0, 0);
  printf ("shared memory22 attached at address %p\n", shared_memory);
   printf ("name=%s\n", shared_memory[i]);
   printf ("%s\n", shared_memory[i+1]);
   printf ("%s\n", shared_memory[i+2]);
  /* Detach the shared memory segment. */
  shmdt (shared_memory);
   return 0;
}

Но я не получаю желаемого результата.вывод, который я получил:

shared memory attached at address 0x7fff0fd2d460
Segmentation fault

Любой может помочь мне с этим.Это правильный способ инициализации shared_memory[3].

Спасибо.

Ответы [ 3 ]

16 голосов
/ 30 августа 2011
char* shared_memory[3];
...
shared_memory[3] = (char*) shmat (segment_id, 0, 0);

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

Ситуация становится окончательно плохой, когда вы пытаетесь использовать указатели с shared_memory[0] по shared_memory[2],потому что эти указатели никогда не были инициализированы.Они заполнены бессмысленным мусором из стека - таким образом, ошибка сегментации.

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

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

13 голосов
/ 29 января 2015

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

// write.c

#include <stdio.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/stat.h>

int main ()
{
  key_t shm_key = 6166529;
  const int shm_size = 1024;

  int shm_id;
  char* shmaddr, *ptr;
  int next[2];

  printf ("writer started.\n");

  /* Allocate a shared memory segment. */
  shm_id = shmget (shm_key, shm_size, IPC_CREAT | S_IRUSR | S_IWUSR);

  /* Attach the shared memory segment. */
  shmaddr = (char*) shmat (shm_id, 0, 0);

  printf ("shared memory attached at address %p\n", shmaddr);

  /* Start to write data. */
  ptr = shmaddr + sizeof (next);
  next[0] = sprintf (ptr, "mandy") + 1;
  ptr += next[0];
  next[1] = sprintf (ptr, "73453916") + 1;
  ptr += next[1];
  sprintf (ptr, "amarica");
  memcpy(shmaddr, &next, sizeof (next));
  printf ("writer ended.\n");

  /*calling the other process*/
  system("./read");

  /* Detach the shared memory segment. */
  shmdt (shmaddr);
  /* Deallocate the shared memory segment.*/
  shmctl (shm_id, IPC_RMID, 0);

  return 0;
}

// read.c

#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>

int main ()
{
  key_t shm_key = 6166529;
  const int shm_size = 1024;

  int shm_id;
  char* shmaddr, *ptr;
  char* shared_memory[3];
  int *p;

  /* Allocate a shared memory segment. */
  shm_id = shmget (shm_key, shm_size, IPC_CREAT | S_IRUSR | S_IWUSR);

  /* Attach the shared memory segment. */
  shmaddr = (char*) shmat (shm_id, 0, 0);

  printf ("shared memory attached at address %p\n", shmaddr);

  /* Start to read data. */
  p = (int *)shmaddr;
  ptr = shmaddr + sizeof (int) * 2;
  shared_memory[0] = ptr;
  ptr += *p++;
  shared_memory[1] = ptr;
  ptr += *p;
  shared_memory[2] = ptr;
  printf ("0=%s\n", shared_memory[0]);
  printf ("1=%s\n", shared_memory[1]);
  printf ("2=%s\n", shared_memory[2]);

  /* Detach the shared memory segment. */
  shmdt (shmaddr);
  return 0;
}

// Результат выполнения:

> [lex:shm]$ ./write
> writer started.
> shared memory attached at address 0x7fa20103b000 
> writer ended.
> shared memory attached at address0x7fd85e2eb000
> 0=mandy
> 1=73453916
> 2=amarica
0 голосов
/ 30 августа 2011

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

...