<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: x0rw</title>
    <description>The latest articles on DEV Community by x0rw (@x0rw).</description>
    <link>https://dev.to/x0rw</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2922357%2F2eaca246-602c-405f-8fee-995e44983a5a.png</url>
      <title>DEV Community: x0rw</title>
      <link>https://dev.to/x0rw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/x0rw"/>
    <language>en</language>
    <item>
      <title>IpcArc&lt;T&gt;: A Design Document for Inter-Process Communication in Rust</title>
      <dc:creator>x0rw</dc:creator>
      <pubDate>Tue, 01 Jul 2025 21:24:32 +0000</pubDate>
      <link>https://dev.to/x0rw/ipcarc-a-design-document-for-inter-process-communication-in-rust-16pf</link>
      <guid>https://dev.to/x0rw/ipcarc-a-design-document-for-inter-process-communication-in-rust-16pf</guid>
      <description>&lt;p&gt;(This document is a preliminary draft and has not been implemented or finished yet. Feedback and comments are welcome)&lt;br&gt;
Linked github repo: &lt;a href="https://github.com/x0rw/ipc-arc" rel="noopener noreferrer"&gt;https://github.com/x0rw/ipc-arc&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Abstract
&lt;/h2&gt;

&lt;p&gt;Rust provides safe and ergonomic primitives such as &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt; for sharing data between threads within the same process. However, there is no standard mechanism for safely and transparently sharing data across process boundaries. While developers can use operating system facilities like shared memory, pipes, and sockets to achieve inter-process communication (IPC), these tools are often low-level, error-prone, and platform-specific.&lt;/p&gt;

&lt;p&gt;The purpose of this design document is to propose and outline a new crate: &lt;code&gt;IpcArc&amp;lt;T&amp;gt;&lt;/code&gt;. This crate introduces a high-level abstraction that allows developers to share data across processes with a familiar and ergonomic interface, similar to Arc. It leverages shared memory under the hood and aims to provide zero-copy, lock-free (when possible), and safe inter-process sharing of Rust values&lt;/p&gt;
&lt;h2&gt;
  
  
  Goals
&lt;/h2&gt;

&lt;p&gt;The main goal of this crate is to provide a way to safetly and ergonomically share data between processes leveraging shared memory.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Safe inter-process communication: preventing common IPC errors like memory corruption and data races,&lt;/li&gt;
&lt;li&gt;Ownership managment: reference counting.&lt;/li&gt;
&lt;li&gt;Synchonisation mechanisms: inter-process mutexes.&lt;/li&gt;
&lt;li&gt;Ergonomic API:&lt;/li&gt;
&lt;li&gt;zero-copy access: on POD types.
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  High level design
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;IpcArc&amp;lt;T&amp;gt;&lt;/code&gt;  will primarily leverage memory-mapped files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When you create &lt;code&gt;IpcArc&amp;lt;T&amp;gt;&lt;/code&gt; instance a shared-memory region will be allocated large enough to hold our type T and its metadata&lt;/li&gt;
&lt;li&gt;Other processes will be able to attach to this memory region by a unique identifier specified by the owning process&lt;/li&gt;
&lt;li&gt;Each shared type will be reference counted in the shared memory itself&lt;/li&gt;
&lt;li&gt;Synchronization: through pshared mutex&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Proposed API design:
&lt;/h2&gt;

&lt;p&gt;The owning process can do&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;shared_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IpcArc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;IpcArc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"shared_identifier_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;77u64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"failed to create a shared memory region..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On another process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;shared_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IpcArc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u64&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;IpcArc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"shared_identifier_1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Memory region doesn't exist..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then on either processes we can aquire and mutate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shared_data&lt;/span&gt;&lt;span class="nf"&gt;.aquire&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// aquire the lock &lt;/span&gt;
&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="nf"&gt;.as_ref_mut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;344&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c1"&gt;// mutate&lt;/span&gt;
&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="nf"&gt;.drop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                       &lt;span class="c1"&gt;// drop the lock&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Suggested structure design:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;IpcArc&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                  &lt;span class="c1"&gt;// ptr to the data in shared mem&lt;/span&gt;
    &lt;span class="n"&gt;mutex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IpcArcMutex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// inter-process mmutex in shared mem&lt;/span&gt;
    &lt;span class="n"&gt;ref_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AtomicUsize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="c1"&gt;// atomic ref count in mem too&lt;/span&gt;
    &lt;span class="n"&gt;_phantom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;PhantomData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Shared memory layout
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-----------------------------------+
|       SHARED MEMORY SEGMENT       |
|   (Accessible by all processes)   |
|      through an identifier        |
+-----------------------------------+
|                                   |
|  +-----------------------------+  |
|  |           HEADER            |  |
|  | (Magic Number / size???)    |  |
|  +-----------------------------+  |
|                                   |
|  +-----------------------------+  |
|  |     INTER-PROCESS ATOMIC    |  |
|  |       REFERENCE COUNT       |  |
|  +-----------------------------+  |
|                                   |
|  +-----------------------------+  |
|  |     INTER-PROCESS MUTEX     |  |
|  |         STATE               |  |
|  +-----------------------------+  |
|                                   |
|  +-----------------------------+  |
|  |           Type T            |  |
|  +-----------------------------+  |
|                                   |
+-----------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Crates and Syscall:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://man7.org/linux/man-pages/man3/shm_open.3.html" rel="noopener noreferrer"&gt;shm_open&lt;/a&gt;: Create or/and open a shared memory object.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://man7.org/linux/man-pages/man3/ftruncate.3p.html" rel="noopener noreferrer"&gt;ftruncate&lt;/a&gt;: Resize the requested memory.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://man7.org/linux/man-pages/man2/mmap.2.html" rel="noopener noreferrer"&gt;mmap&lt;/a&gt;: maps the shared memory object to the current process.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://man7.org/linux/man-pages/man3/munmap.3p.html" rel="noopener noreferrer"&gt;munmap&lt;/a&gt;, &lt;a href="https://man7.org/linux/man-pages/man2/close.2.html" rel="noopener noreferrer"&gt;close&lt;/a&gt;: close and unmap the memory&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://man7.org/linux/man-pages/man3/shm_unlink.3p.html" rel="noopener noreferrer"&gt;shm_unlink&lt;/a&gt;: delete the shared memory object when the ref count reaches 0.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;we will mainly use &lt;code&gt;nix&lt;/code&gt; crate for a safe and ergonomic wrapper around these syscalls.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>opensource</category>
      <category>performance</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
