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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7237540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:31:51  来源:igfitidea点击:

how to use shared memory to communicate between two processes

cipcprocessshared-memory

提问by maddy

I am trying to communicate between two processes. I am trying to save data(like name, phone number, address) to shared memory in one process and trying to print that data through other process.

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

process1.c

进程1.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

进程2.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;
}

But I am not getting the desired output. the output which i got is:

但我没有得到所需的输出。我得到的输出是:

shared memory attached at address 0x7fff0fd2d460
Segmentation fault

Anyone can please help me with this. Is this the correct way of initializing shared_memory[3].

任何人都可以请帮我解决这个问题。这是初始化的正确方法吗shared_memory[3]

Thank you.

谢谢你。

回答by hmakholm left over Monica

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

You declare shared_memoryas an array capable of holding three pointers to char, but what you actually do with it is to write a pointer one place behind the end of the array. Since there is no telling what the memory there is otherwise used for, what happens next is generally unpredictable.

您声明shared_memory为一个能够保存三个指向 char 的指针的数组,但您实际上用它做的是在数组末尾后面一个位置写入一个指针。由于不知道那里的内存是用来做什么的,接下来会发生什么通常是不可预测的。

Things go conclusively bad afterwards when you try to make use of the pointers in shared_memory[0]through shared_memory[2], because those pointers have never been initialized. They are filled with meaningless garbage from the stack -- thus the segmentation fault.

当您尝试使用shared_memory[0]through中的指针时,事情最终会变得很糟糕shared_memory[2],因为这些指针从未被初始化。它们充满了来自堆栈的无意义垃圾——因此是分段错误。

It seems, in general, that you're failing to distinguish between the array and its elements. You should go and make yourself a lotmore comfortable with arrays and pointers in sequential code before you try your hand at shared-memory IPC.

一般来说,您似乎无法区分数组及其元素。你应该去,让自己有很多更舒适的顺序代码数组和指针,你试试你在共享内存IPC前手。

Note that shared memory is one of the more easy-to-get-wrong ways of doing IPC out there. Unless you have rigid efficiency constraints and are going to exchange a lotof data, it's much easier to work with pipes, named pipes, or sockets.

请注意,共享内存是一种更容易出错的 IPC 方式。除非您有严格的效率限制并且要交换大量数据,否则使用管道、命名管道或套接字要容易得多。

回答by Lex Pro

The other two answers told you what's wrong, but I want to give you a runnable code. You can modify it to pass anything, the principle is you need to save the length of every element you passed to the other side.

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

//write.c

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

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

//Result of run:

//运行结果:

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

回答by Ioan

You should be reserving enough shared memory to exchange the data. Processes aren't supposed to access each others memory, even if using shared pointers. Keep in mind only the raw data you write during runtime is shared, there's no type checking or any other metadata passed. You can use a common structure, if your data allows it using fixed-size arrays, to access the data more easily. Otherwise, you'll have to manually marshal the data between the processes.

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