I'm trying to share some data between different processes but I would like to use the same address in all of them.
From what I've read, it seems that this should be possible using mmap()
with the MAP_FIXED
flag (or MAP_FIXED_NOREPLACE
).
Some people suggest to create a shared block and then broadcast the address of that memory block to all the other processes. This comment is a good summary of the whole idea.
So I tried to implement that into this example. There are a sender and a receiver. The sender will create a shared block of memory. The receiver tries to allocate that block of memory at the same address. The address is passed around using a shared memory block too.
The issue is that the receiver can't map the memory object to said address. I get EINVAL error.
Is it possible to do what I'm trying? If so, how or what am I doing wrong in this example?
// 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, O_CREAT | O_EXCL | O_RDWR, 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, RDWR, MAP_SHARED, 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, 0600);
int fd_addr = shm_open(SHM_DATA_ADDR, O_RDONLY, 0600);
ftruncate(fd, SIZE);
ftruncate(fd_addr, SIZE_ADDR);
// Establish mapping between address space and memory object
void **data_addr = (void **)mmap(0, SIZE_ADDR, PROT_READ, MAP_SHARED, fd_addr, 0);
int *data = (int *)mmap(*data_addr, SIZE, PROT_READ, MAP_FIXED, fd, 0);
printf("%p\n", data_addr);
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;
}