Announcing iceoryx2 v0.6.0
Christian Eltzschig - 17/05/2025
![]() |
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!
![]() |
- Discuss on Reddit
- Project iceoryx2 on GitHub
- Project iceoryx2 RMW for ROS on GitHub
- Project on crates.io
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
- Zero-Copy Cross-Language Inter-Process Communication
- Command Line Client
- Microservice Architecture and BuiltIn Services
- ZeroCopySend and Type-Safe Communication
- Other Feature Highlights
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++ |
|
|
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++ |
|
|
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:
config/iceoryx2.toml
in the current project directory$HOME/.config/iceoryx2/iceoryx2.toml
/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.