如何在不同进程中将共享内存映射到相同地址?

问题描述

我试图在不同进程之间共享一些数据,但是我想在所有进程中使用相同的地址。 从我阅读的内容来看,似乎可以将mmap()MAP_FIXED标志(或MAP_FIXED_NOREPLACE)一起使用。 有人建议创建一个共享块,然后将该存储块的地址广播给所有其他进程。 This comment is a good summary of the whole idea.

所以我尝试将其实现到this example中。有一个发送者和一个接收者。发送者将创建一个共享的内存块。接收方尝试在同一地址分配该内存块。该地址也使用共享内存块传递。

问题是接收者无法将内存对象映射到所述地址。 我收到EINVAL错误。

是否可以做我正在尝试的事情?如果是这样,在此示例中我怎么做或在做错什么?

// header.h

#pragma once

#define SHM_DATA_ADDR "/bitarray-addr"
#define SHM_DATA "/bitarray-data"

#define NUM 3
#define SIZE (NUM * sizeof(int))
#define SIZE_ADDR (sizeof(void *))
// sender.c

#include "header.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stddef.h>

int main() {
  // Open the shared memory object for read-only access
  // Set permissions
  int fd      = shm_open(SHM_DATA,O_CREAT | O_EXCL | O_RDWR,0600);
  int fd_addr = shm_open(SHM_DATA_ADDR,0600);

  ftruncate(fd,SIZE);
  ftruncate(fd_addr,SIZE_ADDR);

  // Establish mapping between address space and memory object
  int RDWR = PROT_READ | PROT_WRITE;
  int *data        = (int *)mmap(0,SIZE,RDWR,MAP_SHARED,fd,0);
  void **data_addr = (void **)mmap(0,SIZE_ADDR,fd_addr,0);
  *data_addr = data;

  printf("%p\n",data);
  printf("%p\n",data_addr);
  printf("%p\n",*data_addr);

  // Unmap address space
  munmap(data_addr,SIZE);
  munmap(data,SIZE);

  // Close file descriptors
  close(fd_addr);
  close(fd);

  return EXIT_SUCCESS;
}
// receiver.c

#include "header.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stddef.h>
#include <errno.h>

int main() {
  // Open the shared memory object for read-only access
  // Set permissions
  int fd      = shm_open(SHM_DATA,O_RDONLY,SIZE_ADDR);

  // Establish mapping between address space and memory object
  void **data_addr = (void **)mmap(0,PROT_READ,0);
  int *data        = (int *)mmap(*data_addr,MAP_FIXED,0);

  printf("%p\n",*data_addr);
  printf("%p\n",data); 

  // Unmap address space
  munmap(data_addr,SIZE_ADDR);
  munmap(data,SIZE);

  // Close file descriptors
  close(fd_addr);
  close(fd);

  // Destroy shared memory object
  shm_unlink(SHM_DATA_ADDR);
  shm_unlink(SHM_DATA);

  return EXIT_SUCCESS;
}

解决方法

mmap(2) man page中,重点是我的:

flags参数确定是否更新了映射 对于映射相同区域的其他进程可见,以及是否 更新将传递到基础文件。此行为是 通过在标记中包含恰好是以下值之一来确定:[MAP_SHAREDMAP_SHARED_VALIDATEMAP_PRIVATE]

此外,可以对以下零个或多个值进行或运算 标志:[MAP_ANONYMOUSMAP_FIXED

在接收方代码中,您具有:

int *data        = (int *)mmap(*data_addr,SIZE,PROT_READ,MAP_FIXED,fd,0);

其中不包含MAP_SHAREDMAP_SHARED_VALIDATEMAP_PRIVATE中的任何一个,因此是错误。甚至在错误部分中明确指出:

EINVALflags不包含MAP_PRIVATEMAP_SHAREDMAP_SHARED_VALIDATE

将其更改为MAP_SHARED | MAP_FIXED并为我成功运行。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...