Подтвердить что ты не робот

Как использовать общую память для связи между двумя процессами

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

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].

Спасибо.

4b9b3361

Ответ 1

char* shared_memory[3];
...
shared_memory[3] = (char*) shmat (segment_id, 0, 0);

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

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

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

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

Ответ 2

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

//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

Ответ 3

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