问题描述
我试图在不同进程之间共享一些数据,但是我想在所有进程中使用相同的地址。
从我阅读的内容来看,似乎可以将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_SHARED
,MAP_SHARED_VALIDATE
,MAP_PRIVATE
]此外,可以对以下零个或多个值进行或运算 标志:[
MAP_ANONYMOUS
,MAP_FIXED
等
在接收方代码中,您具有:
int *data = (int *)mmap(*data_addr,SIZE,PROT_READ,MAP_FIXED,fd,0);
其中不包含MAP_SHARED
,MAP_SHARED_VALIDATE
,MAP_PRIVATE
中的任何一个,因此是错误。甚至在错误部分中明确指出:
EINVAL
:flags
不包含MAP_PRIVATE
,MAP_SHARED
或MAP_SHARED_VALIDATE
。
将其更改为MAP_SHARED | MAP_FIXED
并为我成功运行。