- Iceoryx Architecture
1.1 Overview
This section outlines the architectural design and core principles of Eclipse Iceoryx, a zero-copy inter-process communication (IPC) middleware designed for high-performance systems. ### 1.2 Software Layers
Eclipse Iceoryx is structured into several modular components that work together to enable efficient, safe, and scalable communication between processes. The following sections describe these key modules. ### 1.3 Components and Libraries
The framework consists of multiple libraries, each serving a distinct purpose in the system. #### 1.3.1 Iceoryx Hoofs
Handy Objects Optimized For Safety (hoofs) provides foundational utilities such as fixed-size containers, thread-safe data structures, and modern C++ abstractions aligned with upcoming ISO standards. These building blocks are optimized for deterministic behavior and real-time performance, making them suitable for safety-critical environments. #### 1.3.2 Iceoryx Posh
The iceoryx_posh module (POSIX SHared memory) forms the core of Iceoryx’s IPC capabilities, leveraging shared memory for zero-copy data transfer. Core Namespaces:- popo: Stands for Posh Ports, offering user-facing APIs like Publisher and Subscriber for data exchange.
capro: Implements the Canonical Protocol, enabling service discovery and connection management between publishers and servers.mepoo: Short for Memory Pool, manages shared memory chunks viaMemoryManagerand reference-counted pointers to prevent memory leaks.version: Handles ABI versioning and compatibility checks across different builds.build: Contains compile-time configurable limits, such as maximum number of services or instances.
Gateway Support:- The gw namespace defines abstractions used by gateway implementations, particularly for bridging to other protocols.
RouDi Middleware Daemon:- The roudi namespace includes classes used by the RouDi daemon, which coordinates shared memory segments and process registration.
1.3.3 C Bindings
The iceoryx_binding_c component exposes the functionality of iceoryx_posh through a C API, enabling integration with C-based applications and language bindings. #### 1.3.4 Iceoryx DDS Gateway
iceoryx_dds implements a bidirectional bridge to DDS (Data Distribution Service), using Eclipse Cyclone DDS as the underlying transport. This allows Iceoryx nodes to communicate over networks such as Ethernet while maintaining interoperability with DDS-based systems. #### 1.3.5 System Introspection
Introspection tools provide runtime visibility into system state, including active connections, memory usage, and publisher-subscriber topology. These features are useful for debugging and monitoring in production environments. 2. Design Goals and Limitations
2.1 Primary Objectives
- Deliver ultra-low-latency, high-throughput IPC across diverse operating systems.
- Provide a safe, modern C++ API with predictable performance characteristics.
- Support dynamic service discovery without centralized brokers.
- Remain payload-agnostic—no restrictions on data types or schemas.
- Align with communication models from AUTOSAR Adaptive and ROS 2.
- Enable development of protocol gateways (e.g., to DDS, SOME/IP).
- Meet automotive-grade quality requirements for reliability and maintainability.
- Leverage contemporary C++ practices without sacrificing determinism.
2.2 Out-of-Scope Features
- No built-in data modeling tools, IDL compilers, or code generation frameworks.
- Not intended for microcontrollers with less than 1MB RAM.
- Does not aim for full compliance with the DDS specification.
- Frequently Encountered Issues
3.1 Running in Docker Environments
Yes, Iceoryx can operate within Docker containers. Refer to the icedocker example for configuration guidance. ### 3.2 SIGABRT Due to Insufficient Shared Memory
Ensure the container is launched with sufficient shared memory: ``` docker run -it --shm-size="2g" your_image
Verify available space using: ```
df -H /dev/shm
3.3 Checking if RouDi is Active
RouDi uses a file lock at /tmp/roudi.lock. To check its status: ```
flock -n /tmp/roudi.lock echo "RouDi is not running"
If the comand exits immediately, no instance is running. ### 3.4 Sample Loss in Pub/Sub Scenarios
Sample loss may occur when publishers outpace subscribers. Mitigation strategies include: - Matching or exceeding subscriber polling frequency relative to publication rate.
- Enabling blocking publisher mode (use cautiously).
- Increasing `SubscriberOptions::queueCapacity` up to 256.
- Adjusting `IOX_MAX_CHUNKS_HELD_PER_SUBSCRIBER_SIMULTANEOUSLY` via CMake if higher capacity is needed.
### 3.5 Data Accumulation with Listener
When using `Listener`, callbacks may miss bursts of events. After entering `onSampleReceivedCallback`, only one notification is delivered even if multiple samples arrive. To avoid queue saturation: - Drain the queue completely inside the callback using repeated `take()` calls until empty.
- Alternatively, use `WaitSet` with state conditions, which reliably signals whenever new data is available.
### 3.6 Handling MEPOO Memory Pool Exhaustion
Error: `MEPOO__MEMPOOL_GETCHUNK_POOL_IS_RUNNING_OUT_OF_CHUNKS`Possible fixes: - Expand RouDi's shared memory allocation.
- Balance publish and consume rates.
- Reduce per-subscriber queue depth.
- Use blocking publishers—if acceptable in your use case.
**Note:** Blocking publishers halt all transmissions during backpressure, affecting all connected subscribers. ### 3.7 RouDi Fails to Start – SIGBUS on memset
This typically indicates insufficient system-wide shared memory. Check required size from logs (e.g., ~83MB total in example). Confirm availability: ```
df -H /dev/shm
3.8 Stack Size Considerations
Linux defaults usually provide adequate stack space (~8MB). However, platforms like Windows default to 1MB, which may cause stack overflow before main() starts. For executables on Windows, increase the stack size via linker flags in CMake: ```
target_link_options(single_process BEFORE PRIVATE /STACK:3500000)
Adjust accordingly for other toolchains. ### 3.9 Reproducing CI Failures Locally
Use the provided script to replicate CI environments: ```
cd tools/scripts
./ice-env.sh enter ubuntu:18.04
This creates a Docker container with dependencies matching the CI setup. ### 3.10 Process Termination Best Practices
To ensure clean shutdowns of RouDi and client processes, send SIGINT or SIGTERM. Both RouDi and application processes should register signal handlers to allow graceful cleanup of shared memory resources. ### 3.11 Using Iceoryx with Bazel
To integrate Iceoryx as an external dependency in Bazel: In WORKSPACE: ```
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
IOX_COMMIT = "your-commit-hash"
http_archive( name = "eclipse_iceoryx", sha256 = "your-sha256-checksum", strip_prefix = "iceoryx-" + IOX_COMMIT, url = "https://github.com/eclipse-iceoryx/iceoryx/archive/" + IOX_COMMIT + ".zip", )
load("@eclipse_iceoryx//bazel:load_repositories.bzl", "load_repositories") load("@eclipse_iceoryx//bazel:setup_repositories.bzl", "setup_repositories") load_repositories() setup_repositories()