web-dev-qa-db-fra.com

comment utiliser la mémoire partagée pour communiquer entre deux processus

J'essaie de communiquer entre deux processus. J'essaie de sauvegarder des données (comme le nom, le numéro de téléphone, l'adresse) dans la mémoire partagée dans un processus et d'essayer de les imprimer par le biais d'un autre processus.

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;
}

Mais je n’obtiens pas le résultat souhaité. Le résultat obtenu est le suivant:

shared memory attached at address 0x7fff0fd2d460
Segmentation fault

Tout le monde peut m'aider s'il vous plait. Est-ce la bonne façon d'initialiser shared_memory[3]?.

Je vous remercie.

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

Vous déclarez shared_memory comme un tableau capable de contenir trois pointeurs, mais vous écrivez un pointeur à une place derrière la fin du tableau . Comme on ne sait pas à quoi sert la mémoire, la suite est généralement imprévisible.

Les choses vont définitivement mal par la suite lorsque vous essayez d'utiliser les pointeurs de shared_memory[0] à shared_memory[2], car ces pointeurs n'ont jamais été initialisés. Ils sont remplis d'ordures sans signification de la pile - d'où la faute de segmentation.

Il semble en général que vous ne parveniez pas à faire la distinction entre le tableau et ses éléments. Vous devriez vous rendre beaucoup plus à l'aise avec les tableaux et les pointeurs dans le code séquentiel avant de tenter votre chance à l'IPC à mémoire partagée.

Notez que la mémoire partagée est l’un des moyens les plus faciles à utiliser IPC. Sauf si vous avez des contraintes d'efficacité strictes et que vous allez échanger beaucoup de données, il est beaucoup plus facile de travailler avec des tubes, des tubes nommés ou des sockets.

15
Henning Makholm

Les deux autres réponses vous ont dit ce qui ne va pas, mais je veux vous donner un code exécutable. Vous pouvez le modifier pour passer n'importe quoi, le principe est que vous devez enregistrer la longueur de chaque élément que vous avez passé de l'autre côté.

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

// Résultat de l'exécution:

> [Lex:shm]$ ./write
> writer started.
> shared memory attached at address 0x7fa20103b000 
> writer ended.
> shared memory attached at address0x7fd85e2eb000
> 0=mandy
> 1=73453916
> 2=amarica
12
Lex Pro

Vous devriez réserver suffisamment de mémoire partagée pour échanger les data . Les processus ne sont pas censés accéder à la mémoire des autres, même si vous utilisez des pointeurs partagés. N'oubliez pas que seules les données brutes que vous écrivez au cours de l'exécution sont partagées. Aucune vérification de type ni aucune autre métadonnée n'est transmise. Vous pouvez utiliser une structure commune, si vos données le permettent à l'aide de tableaux de taille fixe, pour accéder aux données plus facilement. Sinon, vous devrez classer manuellement les données entre les processus.

0
Ioan