title: Is there a way to an share address mapping between two unrelated processes on Linux?
body: <p>I'm assuming if this is possible it would most likely be via <code>mmap</code></p>
  <p>My original question was can <code>mmap(</code>) return the same pointer for each user of the same piece of shared memory?
  Ultimately an address in each processes address space maps to the same physical memory.
  The question is whether the address provided to each process can be made the same somehow.</p>
  <hr />
  <p>Why does this matter?</p>
  <p>Consider the case of sharing a data structure which contains pointers.
  If the address mapping is shared those pointers are valid for both processes.
  If the address mapping is not shared then a pointer may point to the address space for the process that wrote it.
  If the other process tries to read it, it will trigger an access violation.</p>
  <p>For shared libraries we rely on position independent code but there can still be pointers that the loader needs to adjust on load.
  (I am unclear whether this is done exactly once or whether each process gets its own private copy of pages containing such pointers adjusted to fit its own address space).</p>
  <p>If the address mapping is not shared then for data we either need to create position independent structures (unfortunate acronym) using offsets instead of absolute pointers
  or limit ourselves to data structures not containing any pointers.</p>
  <p>In my application I have several data structures I wish to share which are essentially vectors.
  I do not wish to persist or serialise/deserialise them. I want the same physical memory to be used by each process.
  Basically its a search problem - the shared data is the haystack and each process searches for its own set of needles.
  For various reasons we do not want them to be threads though it would eliminate this question entirely because threads do share the address space.</p>
  <p>I can create vectors inside shared memory using a custom allocator.
  Say:</p>
  <pre><code>SharedMemoryAllocator sharedAlloc(somePointerFromMmap);
  class Foo
  {
     std::vector&lt;Bar, SharedMemoryAllocator&gt;   A;
     std::vector&lt;Snafu, SharedMemoryAllocator&gt; B;
  
     Foo(SharedMemoryAllocator&amp; sharedAlloc):
        A(sharedAlloc)
        B(sharedAlloc)
     {
     }
  };
  </code></pre>
  <p>If the address mapping is shared it is safe to use such an allocator for the complete structure:</p>
  <pre><code>unique_ptr&lt;Foo&gt; fubar = sharedAlloc.new(Foo(sharedAlloc));
  </code></pre>
  <p>Because the pointers to storage for A and B with <code>*fubar</code> will be in the same address space for both.</p>
  <p>If on the other hand the address mapping is not shared I can only safely share the underlying memory blocks to which A and B point.</p>
  <p>That is each process must have its own local instance of Foo where each vector is constructed by attaching to a shared memory block provided by the allocator.
  This is more portable but uglier.</p>
  <p>Technically neither conforms to the C++ spec without the addition of <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0593r2.html" rel="nofollow noreferrer">std::bless()</a> and other wizardry.
  So we are in undefined (or rather platform defined) behaviour anyway. But then so is <em>'safe'</em> use of <code>malloc</code> (see link above).</p>
  <hr />
  <p>As far as I know nothing about the address returned by <code>mmap()</code> is guaranteed by Posix or Linux except for the case where you ask for a specific address and the call does not fail.</p>
  <p>So if it happens to work it is probably at best undefined behaviour.
  Its generally a bad idea to rely on undefined behaviour for all the usual reasons.
  But perhaps it is actually platform defined rather than undefined?</p>
  <p>As mentioned the exception is for a <a href="https://www.boost.org/doc/libs/1_53_0/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_region.mapped_region_fixed_address_mapping" rel="nofollow noreferrer">fixed address mapping</a>
  but how can you get two independent processes to agree on the same safe address to use in advance?
  One possibility is given <a href="https://stackoverflow.com/a/11035560/1569204">here</a></p>
  <p>This suggests you need a second shared memory segment or some other IPC mechanism to share the address assigned to the creator of the shared memory block you wish to use.</p>
  <p>Is this the correct way? Is it the only way?</p>
  <hr />
  <p>Looking at <a href="https://stackoverflow.com/a/28576674/1569204">When would one use mmap MAP_FIXED?</a> - the main legitimate use of MAP_FIXED is to remap different kinds of memory segments which need to be at the same relative address to each other when loading a library</p>
  <p>However other people are using this the way I suggest.
  The other answer to that question mentions:</p>
  <blockquote>
  <ul>
  <li>Shared memory may contain pointers.</li>
  </ul>
  </blockquote>
  <p>I found a few other references to people using MAP_FIXED to do this
  but I have not yet found a working example.</p>
  <p>Has use of MAP_FIXED this way been rendered non-functional by <a href="https://en.wikipedia.org/wiki/Address_space_layout_randomization" rel="nofollow noreferrer">ASLR</a> ?</p>
  <p>It is actually the case that you can only share address space in very specific circumstances:</p>
  <p>For example only if:</p>
  <ul>
  <li><p>You use MAP_ANONYMOUS and</p>
  </li>
  <li><p>pass the FD to an unrelated process via <a href="https://stackoverflow.com/a/2358843/1569204">sendmsg/recvmsg</a></p>
  <p>Apparently <a href="https://stackoverflow.com/a/11355725/1569204">linux does not support I_SENDFD/I_RECVFD</a></p>
  </li>
  </ul>
  <p>Will MAP_FIXED_NOREPLACE then work in this case?</p>
  <p>Does it make a difference whether you use shm_open() or open() ?</p>
  <p>I've looked into the code for <a href="https://www.boost.org/doc/libs/1_63_0/doc/html/interprocess/sharedmemorybetweenprocesses.html" rel="nofollow noreferrer">boost interprocess</a> and it does not seem to use either MAP_FIXED or sendmsg.
  It seems this is <a href="https://stackoverflow.com/a/72310394/1569204">not supported</a>.</p>
  <p>The approach I am currently trying is simplifying:</p>
  <p>process A:</p>
  <pre><code>fd = open(&quot;foobar&quot;, O_RDWR);
  void* address = mmap(nullptr, PROT_READ|PROT_WRITE, MAP_SHARED, fd);
  (*address) = address;
  </code></pre>
  <p>process B:</p>
  <pre><code>fd = open(&quot;foobar&quot;, O_RDONLY);
  void* addressRequested = readAddressFromFoobar();       
  void* address = mmap(addressRequested, PROT_READ, MAP_SHARED|MAP_FIXED, fd);
  </code></pre>
  <p>This fails with E_NOMEM.
  While if I replace addressRequested with a nullptr it succeeded and I can access the same data but can't rely on any pointers.</p>
  <p>Can somebody demonstrate or link to a way to do this that works
  or explain definitively why this cannot ever work in current Linux.</p>
  <p>I am quite aware that we can share objects using internal offsets instead of pointers but loses a lot of convenience. STL types generally assume they can use pointers. I do not wish to write my own versions of every container I wish to use if I can possibly avoid it.</p>
  <hr />
  <p>Apparently boost works around this issue by providing containers that use smart pointers instead of raw pointers. I had not realised that. This is a good solution to the general problem but a different question from this one. Locating a canonical explanation of that would be useful as a better answer to <a href="https://stackoverflow.com/q/72310393/1569204">Does boost interprocess support sharing objects containing pointers between processes?</a> or indeed a better question.</p>