【问题标题】:how to use shared memory to communicate between two processes如何使用共享内存在两个进程之间进行通信
【发布时间】:2011-11-06 10:37:42
【问题描述】:

我正在尝试在两个进程之间进行通信。我正在尝试将数据(例如姓名、电话号码、地址)保存到一个进程中的共享内存中,并尝试通过其他进程打印该数据。

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]的正确方法吗?

谢谢。

【问题讨论】:

    标签: c ipc process shared-memory


    【解决方案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
      

      【讨论】:

      • 在 read.c 期间调用 IPC_CREAT 不会创建一组全新的共享内存而不是获取现有的吗?
      【解决方案3】:

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

      【讨论】:

        最近更新 更多