Announcing iceoryx2 v0.6.0

Christian Eltzschig - 17/05/2025

iceoryx2 rust cpp c

Header

What Is iceoryx2

iceoryx2 is a service-based inter-process communication (IPC) library designed to build robust and efficient decentralized systems. It enables ultra low-latency communication between processes — similar to Unix domain sockets or message queues, but significantly faster and easier to use.

It includes language bindings for C, C++, and Rust, with support for Python planned for an upcoming release.

iceoryx2 supports messaging patterns such as publish-subscribe, events, and the newly introduced request-response stream pattern. It is robust and comes with a decentralized architecture without the need for a central broker.

Check out the iceoryx2 benchmarks and try them out on your platform!

benchmark

Release v0.6.0

Our small company is steadily growing, thanks to our community and our supportive customers. This growth has enabled us to deliver one of our biggest releases yet in terms of features: the iceoryx2 v0.6.0 release.

Request-Response Stream

Introduction

The well-known request-response messaging pattern involves a client sending a request to a server and receiving a corresponding response. A typical example is an operator commanding a robot to move to a specific position, with the robot confirming the command by sending back a response. This is now supported in iceoryx2 - along with much more.

Operating A Robot

In addition to a one-time response, the operator might also be interested in monitoring the robot’s progress in real time. With iceoryx2, a request can initiate a stream of responses - hence the name request-response stream. Instead of simply acknowledging the request, the server can continuously send position updates as the robot moves. Once the robot reaches its destination, the server drops the corresponding object, signaling completion to the client.

Conversely, if the client loses interest - for example, due to a canceled operation - it can let its corresponding object go out of scope. This informs the server to stop processing the request, which could include halting the robot.

Thanks to iceoryx2’s new API, this is implemented with maximum efficiency. Users don’t need to manage request or response IDs manually. Each request-response pair operates on a dedicated connection, complete with built-in overflow and buffer-size controls.

Publish-Subscribe With A Filter

Suppose you're building a service that analyzes camera images to detect facial expressions. You only want images containing faces - not trees. With request-response stream, you can request just the relevant images and receive them as a filtered stream. Irrelevant images are automatically excluded on the server side.

Examples

Currently, there are two request-response examples available in iceoryx2:

Most examples are provided in all supported languages. Check out the examples overview for details.

Zero-Copy Cross-Language Inter-Process Communication

iceoryx2 already supports multiple languages, but until now, it was not possible to connect processes written in different languages - for example, a C++ process with a Rust process. Each process had to remain within its own language domain.

This limitation has been resolved by introducing the ability to define a semantic type name in every supported language.

Let’s say you have a type like TransmissionData that you want to use for communication between Rust and C++. By assigning a shared semantic type name, both languages can now recognize and interpret the data structure as the same conceptual type, enabling seamless zero-copy communication across language boundaries.

Rust

C++

#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct TransmissionData {
    pub x: i32,
    pub y: i32,
    pub funky: u64,
}
struct TransmissionData {
    int32_t x;
    int32_t y;
    uint64_t funky;
}

With the newly introduced ZeroCopySend derive macro in Rust, you can annotate a type and assign it a unique semantic type name - the identifier under which the payload type is known system-wide.

On the C++ side, you can optionally define a static constexpr const char* IOX2_TYPE_NAME member to specify the same semantic type name.

If the semantic type name, size, and alignment match between the Rust and C++ definitions, iceoryx2 will establish a connection between the processes - enabling zero-copy communication across language boundaries.

Rust

C++

#[derive(Debug, Clone, Copy, ZeroCopySend)]
#[type_name(TransmissionData)]
#[repr(C)]
pub struct TransmissionData {
    pub x: i32,
    pub y: i32,
    pub funky: u64,
}
struct TransmissionData {
    static constexpr const char*
        IOX2_TYPE_NAME = "TransmissionData";
    int32_t x;
    int32_t y;
    uint64_t funky;
}

Check out the publish subscribe cross-language example to see a zero-copy inter-process communication between C, C++ and Rust in action - without the need for serialization.

Outlook

Following this release, we’ll begin working on the Python language bindings. Our goal is to offer the same cross-language functionality - enabling zero-copy communication between C, C++, Rust, and Python. This communication shall remain serialization-free as long as the user ensures the memory layout is identical across all languages.

However, as payloads become more complex than simple integers, maintaining compatible layouts becomes more challenging. To address this, we plan to introduce container types in Rust and C++ that are guaranteed to have the same memory layout, allowing us to share data without serialization.

Another concern is that checking only the type name, size, and alignment of a payload may not be sufficient. For example, consider this Rust struct after a refactoring:

#[derive(Debug, Clone, Copy, ZeroCopySend)]
#[type_name(TransmissionData)]
#[repr(C)]
pub struct TransmissionData {
    pub y: i32,
    pub x: i32,
    pub funky: u64,
}

Even though the size and alignment remain unchanged, the internal structure no longer matches the original, which could lead to subtle bugs. That’s why, in the long term, we aim to support interface descriptions of payloads. These descriptions will be stored within the iceoryx2 service and are used for verifying the structural compatibility across languages.

Command Line Client

If you want to debug your iceoryx2 system, list all running services, inspect internal details, or monitor system health, the iceoryx2-cli tool now makes it possible.

You can install it using:

cargo install iceoryx2-cli

Once installed, iox2 offers various commands to help you to:

  • Generate a default configuration file
  • List all nodes or inspect details of a specific node
  • List all services or view detailed configurations of a specific service

Run iox2 --help to explore all available options.

A particularly useful feature is customizable output formatting. This allows easy integration into other tools and pipelines. Currently, JSON, RON, and YAML are supported.

For example, to view all active nodes in your system:

iox2 node list

might output:

(
num: 1,
details: [
    (
        state: Alive,
        id: ("0000000020c8e30b6827192d0000e55e"),
        pid: 58718,
        executable: Some("request_response_client"),
        name: Some(""),
    ),
],
)

To inspect a specific node's details:

iox2 node details 0000000020c8e30b6827192d0000e55e

Similarly, you can list all active services:

iox2 service list

Sample output:

[
PublishSubscribe("My/Funk/ServiceName"),
RequestResponse("My/Funk/ServiceName"),
Event("MyEventName"),
]

To view the full configuration of a particular service:

iox2 service details MyEventName

Microservice Architecture and Built-In Services

A core goal of iceoryx2 is to support deployment in microservice-style architectures. This release introduces the first service of this kind: the "service discovery" service.

We plan to organize these services in two components:

  • Library component (iceoryx2-services-**), which can be embedded into your existing application process
  • Binary tool (iox2 **), which can be run as a stand-alone process to augment your system

The discovery service example demonstrates how to integrate it into your own application. If you’d rather run the service as a standalone process, simply execute:

iox2 service discovery

This "service discovery" service lays the groundwork for upcoming features like network gateways and tunnels. The vision is to enable out-of-the-box communication between iceoryx2 instances across different machines - or even between native and remote instances - by simply launching a gateway process.

ZeroCopySend

True zero-copy communication requires that data is produced directly into shared memory. With iceoryx2, this means loaning an uninitialized sample, passing it to your data-producing function, and then sending it out - without any intermediate copying.

However, for this to work, the data must be compatible with shared memory so that it can be safely interpreted by receiving processes. This means it must be:

  • Self-contained — no use of raw pointers
  • Uniformly represented in memory — no layout ambiguities
  • Trivially destructible

Every process has its own memory address space. A pointer to a shared memory segment in one process may point to something entirely unrelated or invalid in another. Even worse, if the pointer refers to heap memory that only exists in the sender’s process, dereferencing it in the receiver causes undefined behavior.

Uniform memory representation is equally critical. Because shared memory is interpreted directly across processes, any mismatch in field layout or alignment can lead to corruption or undefined behavior. This is particularly relevant in Rust, where the compiler may reorder struct fields unless explicitly instructed not to. That’s why all payload types must use #[repr(C)] to ensure a predictable, C-compatible layout.

To make this safer and easier in Rust, we introduced the ZeroCopySend trait, along with a derive macro. It verifies at compile time that your type satisfies all the necessary constraints. Forget to add #[repr(C)]? Accidentally use a String or Vec? The compiler will catch it. Just annotate your struct with #[derive(ZeroCopySend)] and let the macro guide you.

If you do need complex types like String or Vec, take a look at these examples using custom base library types:

Currently, the ZeroCopySend trait is only available in Rust. We'll see what we can come up with for C and C++ in the future.

Other Feature Highlights

Event services now support a deadline property, which defines the maximum duration within which at least one notification must be received. If a listener port using this feature is attached as a deadline to a waitset (our event multiplexer), the waitset will wake up with an error if no notification arrives before the deadline expires.

See the health monitoring example subscriber for a practical use case.

The iceoryx2 configuration file now follows the XDG directory specification. The search order is:

  1. config/iceoryx2.toml in the current project directory
  2. $HOME/.config/iceoryx2/iceoryx2.toml
  3. /etc/iceoryx2/iceoryx2.toml

Cross-compiling iceoryx2 on Linux is now easier, thanks to a new platform abstraction based on the libc crate. This significantly simplifies builds for environments like Yocto.

cargo build --features libc_platform

Roadmap: What’s Next?

Stay up to date with our ongoing progress by checking out the iceoryx2 Roadmap. Please note that this is a best-effort plan and may change on short notice. If you need a specific feature or have time-critical requirements, feel free to reach out to us.

  • no_std support for embedded and bare-metal use cases
  • Support for embedded platforms such as VxWorks and QNX **
  • Blackboard Messaging Pattern
  • Python language bindings
  • Network communication via Zenoh
  • (Moonshot) Go language bindings

** The availability of open-source support for QNX and VxWorks depends on acquiring free licenses to run these targets in our CI pipeline.

Thank You

We want to thank our community. Your ideas, discussions, and collaborative spirit help shape iceoryx2 every day. Even frustrating bugs become less painful when tackled with humor and openness.

And finally, a big thank you to our customers who share our vision:

To create an open-source, certifiable base and communication library that can be trusted in mission-critical systems.