0

I want to share memory using a file descriptor with another process created via fork. The problem is that I get different address regions from mmap. I want that mmap returns the same address value. Only in such case I can be sure that I really share the memory.

Probably it is possible to use MAP_FIXED flag to mmap, but how to get memory address from shm_open?

Is it possible to share memory via shm_open at all?

Maybe shmget must be used instead?

This is the minimal working example:

#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
  /* Create a new memory object */
  int fd = shm_open( "/dummy", O_RDWR | O_CREAT, 0777 );
  if(fd == -1) {
    fprintf(stderr, "Open failed:%m\n");
    return 1;
  }

  /* Set the memory object's size */
  size_t size = 4096; /* minimal */

  if (ftruncate(fd, size) == -1) {
    fprintf(stderr, "ftruncate: %m\n");
    return 1;
  }

  void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (ptr == MAP_FAILED) return 1;

  void *ptr2 = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  if (ptr2 == MAP_FAILED) return 1;

  printf("%p\n%p\n", ptr, ptr2);

  return 0;
}

Compile it with gcc test.c -lrt.

This is the output:

0x7f3247a78000
0x7f3247a70000

EDIT

If I try to use method described in comment, child does not see changes in memory made by parent. Why? This is how I do it:

In parent:

shm_data = mmap(NULL, shm_size, PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);
...
snprintf(shared_memory, 20, "%p", shm_data);
execl("/path/to/prog", "prog", shared_memory, (char *) NULL);

In child:

...
void *base_addr;
sscanf(argv[1], "%p", (void **)&base_addr);
shm_data = mmap(base_addr, shm_size, PROT_READ, MAP_ANONYMOUS | MAP_SHARED | MAP_FIXED, -1, 0);
...

EDIT2

See also this question: How to get memory address from memfd_create?

Igor Liferenko
  • 1,499
  • 1
  • 13
  • 28
  • If you want the virtual addresses to be the same, then you have to also share the virtual address itself using any of the possible IPC mechanisms. For example, the process can write the virtual address to another shared memory region and the other process can use `MAP_FIXED` with that virtual address. – Hadi Brais Apr 30 '18 at 23:32
  • I think the best way is not to use `shm_open` at all; instead, simply use `mmap` with `MAP_ANONYMOUS` in parent, write the obtained address to in-memory file, pass its descriptor to child, and in child use `MAP_FIXED` with address read from the file descriptor, inherited from parent, as you advised. – Igor Liferenko May 01 '18 at 12:45
  • Another option for passing address to child is in argument list to `execl`. – Igor Liferenko May 01 '18 at 12:52
  • @HadiBrais see **EDIT** – Igor Liferenko May 01 '18 at 13:55
  • Simply using the same virtual address with `MAP_ANONYMOUS` does not make the region shared. You have to use `shm_open`. Passing the virtual address as an argument to `execl` is fine. – Hadi Brais May 01 '18 at 16:57
  • See also https://stackoverflow.com/questions/72194235/is-there-a-way-to-an-share-address-mapping-between-two-unrelated-processes-on-li?noredirect=1#comment127751665_72194235 – Bruce Adams May 20 '22 at 07:30

0 Answers0