How to an Share Address Mapping Between Two Unrelated Processes on Linux

mmap file between unrelated processes

Two independent processes can use mmap(2) to share access to the kernel disk block cache holding the file data:

1) Process A opens a file, makes the file the desired size and creates an mmap(2) window into the file.

2) Process B opens the same file and creates an mmap(2) window into the same file.

3) Now, the same kernel block cache data exist simultaneously in both processes. Either process can modify the data and that data is instantaneously available in the other process.

This is the issue the MAP_SHARED flag is intended to provide.

Sharing Pointers Between Multiple Forked Processes

All data you want to share has to be in the shared segment. This means that both the pointers and the strings have to be in the shared memory.

Sharing something which includes pointers can be cumbersome. This is because mmap doesn't guarantee that a given mapping will end up in the required address.

You can still do this, by two methods. First, you can try your luck with mmap and hope that the dynamic linker doesn't load something at your preferred address.

Second method is to use relative pointers. Inside a pointer, instead of storing a pointer to a string, you store the difference between the address of the pointer and the address of the string. Like so:

char **keys= mmap(NULL, ...);
char *keydata= (char*) keys + npointers * sizeof(char*);
strcpy(keydata, firstring);
keys[0]= (char*) (keydata - (char*) &keys[0]);
keydata+= strlen(firststring)+1;

When you want to access the string from the other process, you do the reverse:

char **keys= mmap(NULL, ...);
char *str= (char*) (&keys[0]) + (ptrdiff_t) keys[0];

It's a little cumbersome but it works regardless of what mmap returns.

Sharing memory mappings under Linux

*nix systems have several APIs for shared memory:

  • BSD: use mmap(). To share memory between unrelated processes, you associate it to a file. You can also share memory between related processes using MAP_ANONYMOUS and fork()ing (but make sure to use -1 as fd for portability).
  • System V: (some people really dislike this one) use shmget() to create/get a reference to a shared memory area, attach to it via shmat(), detach via shmdt(), mark for deletion with shmctl(). You identify shared memory areas by a key, which should be unique.
  • POSIX: use shm_open() then mmap() from the returned file descriptor.

Share std::map between processes with mmap()

This does not work because although you placed the container object into the shared memory, the elements are still allocated from the heap and thus they are not accessible by other processes.

You need a custom allocator that allocates elements in the shared memory. See Creating maps in shared memory for how it is done.

Note that the string class you use must also allocate memory from the shared memory.

In other words, you cannot have pointers to heap memory in the shared memory, because heap memory is not shared between processes. std classes have an allocator template argument, the default one allocates memory from the heap. This needs to be changed to a shared memory allocator to be able to share such objects via shared memory.



Related Topics



Leave a reply



Submit