如何使用共享内存在两个进程之间进行通信

15
我正在尝试在两个进程之间进行通信。我正在尝试在一个进程中将数据(如姓名、电话号码、地址)保存到共享内存中,并尝试通过另一个进程打印该数据。 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个回答

17
char* shared_memory[3];
...
shared_memory[3] = (char*) shmat (segment_id, 0, 0);
你声明了一个能够容纳三个指向char的指针的数组shared_memory,但实际上你在它的末尾处写了一个指针。由于不知道该内存用于什么,接下来会发生什么是不可预测的。
当你试图使用shared_memory[0]shared_memory[2]中的指针时,事情变得非常糟糕,因为这些指针从未被初始化过。它们充满了来自堆栈的无意义垃圾 - 因此会导致分段错误。
总的来说,你似乎没有区分数组和其元素之间的差别。在尝试使用共享内存IPC之前,你应该更加熟练地掌握顺序代码中的数组和指针操作。
请注意,共享内存是一种易错的IPC方式之一。除非你面临严格的效率限制并要交换大量数据,否则使用管道、命名管道或套接字会更加容易。

16

其他两个答案已经告诉你出了什么问题,但我想给你一个可运行的代码。你可以修改它以传递任何东西,原则是你需要保存每个传递到另一侧的元素的长度。

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

//读取.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

在read.c中调用IPC_CREAT会创建一个全新的共享内存集合,而不是获取现有的那个,对吗? - Sherd

0

您应该保留足够的共享内存来交换数据。即使使用共享指针,进程也不应该访问彼此的内存。请记住,仅在运行时编写的原始数据是共享的,没有类型检查或传递任何其他元数据。如果您的数据允许,则可以使用公共结构(例如使用固定大小数组)更轻松地访问数据。否则,您将不得不在进程之间手动编排数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接