[翻译]Iceoryx - 概述

1. Iceoryx 架构

1.1 本节概述

本节简述 Eclipse Iceoryx 的架构和设计原理。
原文地址: concepts/architecture.md

1.2 软件层

Eclipse iceoryx 由以下主要包组成:
在这里插入图片描述

接下来的章节将逐一简要描述这些组件及其库。

1.3 组件和库

下图展示了不同的库及其命名空间:
在这里插入图片描述

1.3.1 Iceoryx hoofs

Handy Objects Optimized For Safety(hoofs)是一个库,包含各种构建块,如固定大小的容器、并发类和来自即将发布的 C++ 标准的新一代 C++ 构造。

有关组件的更多信息,请参阅其详细描述

1.3.2 Iceoryx posh

iceoryx_poshPOSIX SHared memory)包包含与共享内存进程间通信相关的所有内容。

核心库

这一部分描述了核心库的命名空间。

  • popo:命名空间 posh ports 包含用于数据传输的用户 API 类。
  • capro:命名空间 canonical protocol 实现了标准协议模式协议,iceoryx_posh 使用该协议来连接和发现 popo::Publisherpopo::Server
  • mepoo:命名空间 memory pool 包含所有与内存相关的类,例如 MemoryManagerSharedPointer
  • version:命名空间 version 包含 ABI 兼容性检查。
  • build:命名空间 build 包含在编译前可以更改的某些最大值。
网关库
  • 网关库及其命名空间 gw 包含创建网关的通用抽象。这些抽象由 iceoryx_dds 使用。
RouDi 库
  • RouDi 库及其命名空间 roudi 包含 RouDi 中间件守护进程使用的类。

1.3.3 Iceoryx C 绑定

模块 iceoryx_binding_c 使 iceoryx_posh 的进程间通信功能在 C 中可用。

1.3.4 Iceoryx DDS

iceoryx_dds 包提供了一个双向 DDS 网关,使用 Eclipse Cyclone DDS。该网关可用于通过网络(例如以太网)发送数据。

有关更多信息,请参阅Readme

1.3.5 Iceoryx introspection

内省客户端可用于实时调试,并提供当前系统的信息,如内存使用情况和已建立的连接。

有关更多信息,请参阅 icecrystal 示例

2. Iceoryx 目标与非目标

2.1 目标

  • 为各种操作系统提供高性能的进程间通信
  • 安全且灵活的API
  • 动态连接的服务发现功能
  • 对数据无关,不限制负载数据
  • 兼容AUTOSAR Adaptive和ROS 2通信模式
  • 提供构建网络协议网关的基础模块
  • 汽车级软件质量
  • 现代C++

2.2 非目标

  • 提供数据模型和类似IDL或代码生成器的工具
  • 缩小到可以运行在微控制器上(例如,内存小于1MB)
  • 完全符合DDS标准

3 常见问题解答

本小节翻译自:website/FAQ.md

3.1 Iceoryx能在Docker环境中运行吗?

可以。请参阅icedocker示例

3.2 Iceoryx在Docker环境中保留共享内存时崩溃并显示SIGABRT

检查Docker容器的--shm-size标志。容器是否提供了所需的共享内存大小?

3.3 如何判断RouDi是否在运行?

RouDi使用文件锁机制确保一次只运行一个RouDi实例。为此,RouDi会创建并锁定/tmp/roudi.lock。即使RouDi未运行,该文件也会存在。尝试锁定此文件,如果失败,则说明RouDi正在运行。

在命令行中执行:

flock -n /tmp/roudi.lock echo "RouDi is not running"

3.4 发布订阅场景中丢失样本

丢失样本对您的系统不可接受?发布者发送的频率是否高于订阅者接收样本的频率?

可以采取以下措施:

  • 确保接收频率高于发布频率

或者

!!! 注意
使用阻塞发布者功能需要仔细考虑,因为在发布者被阻塞时,其他订阅者将无法接收样本。

另一种可能的解决方案是:

  • SubscriberOptions::queueCapacity增加到最多256
    • 如果256不够,通过CMake开关增加最大值IOX_MAX_CHUNKS_HELD_PER_SUBSCRIBER_SIMULTANEOUSLY

3.5 使用Listener时丢失样本

如果订阅者与Listener结合使用,有些样本可能会在接收队列中等待被取走。Listener使用事件,比WaitSet的状态快,但这也意味着如果发布者在订阅者执行onSampleReceivedCallback时触发了5个事件,它只会在离开回调后触发一次。如果您不注意从队列中取出所有数据,它们将一直留在队列中并填满队列。默认队列大小为256个样本。这意味着在onSampleReceivedCallback中需要循环取出样本,直到take报告队列为空。或者,可以使用WaitSet代替ListenerWaitSet支持状态和事件,如果使用状态,它会在队列中有数据时触发。

3.6 解决错误MEPOO__MEMPOOL_GETCHUNK_POOL_IS_RUNNING_OUT_OF_CHUNKS

可能的解决方案包括以下几种:

  • 增加RouDi的内存配置
  • 确保接收频率高于发布频率
  • 减少SubscriberOptions::queueCapacity,在订阅者一侧的内存池中保存较少的样本
  • 考虑使用阻塞发布者功能。使用该功能需要仔细考虑,因为在发布者被阻塞时,其他订阅者将无法接收样本。

!!! 注意
使用阻塞发布者功能需要仔细考虑,因为在发布者被阻塞时,其他订阅者将无法接收样本。

3.7 iox-roudi启动失败

错误信息如下:

user@iceoryx-host:/# iox-roudi
Log level set to: [Warning]
SharedMemory still there, doing an unlink of /iceoryx_mgmt
Reserving 59736448 bytes in the shared memory [/iceoryx_mgmt]
[ Reserving shared memory successful ]
SharedMemory still there, doing an unlink of /root
Reserving 27902400 bytes in the shared memory [/root]
While setting the acquired shared memory to zero a fatal SIGBUS signal appeared
caused by memset. The shared memory object with the following properties
[ name = /root, sizeInBytes = 27902400, access mode = AccessMode::READ_WRITE,
ownership = OwnerShip::MINE, baseAddressHint = (nil), permissions = 0 ] maybe
requires more memory than it is currently available in the system.

表示没有足够的共享内存。检查:

df -H /dev/shm

查看是否有足够的内存可用。在此示例错误信息中,我们需要59736448(iceoryx管理数据)+ 27902400(用户样本)约83.57mb的共享内存。

3.8 栈大小处理

Iceoryx中间件利用系统的栈内存来记录内部结构。大多数Linux发行版为每个进程提供8MB的栈内存,这对Iceoryx来说已经足够。您可以通过ulimit -a的输出进行检查。

在其他平台(如Windows)上,栈内存有不同的规则。在Windows上,栈内存只有1MB。一般来说,不推荐在Iceoryx中增加栈大小,因为RouDi可能会消耗大量内存而未使用它。尤其是在多线程环境中使用RouDi时,可能会耗尽栈内存并导致内存错误。

Single process示例显示了在Windows上编译和执行时的情况。如果不设置栈大小,应用程序将在进入main()方法时抛出Stack overflow异常。

可以通过在CMake中添加链接器标志解决此问题:

target_link_options(single_process BEFORE PRIVATE /STACK:3500000)

对于其他平台,适用其他标志或解决方案。

CI失败但本地无法复现错误

可以使用tools/scripts/ice_env.sh创建一个Iceoryx开发环境,其配置与CI目标非常相似。例如,如果目标ubuntu 18.04失败,可以创建一个docker容器:

cd tools/scripts
./ice-env.sh enter ubuntu:18.04

这将启动容器,安装Iceoryx所需的所有依赖项并进入环境。

Docker

在Docker环境中,检查是否有足够的内存可用:

# docker stats
CONTAINER ID   NAME            CPU %     MEM USAGE / LIMIT   MEM %     NET I/O       BLOCK I/O     PIDS
367b9fae6c2f   nifty_galileo   0.00%     4.48MiB / 1GiB      0.44%     11.6kB / 0B   17.6MB / 0B   1

如果内存不足,可以使用--shm-size="2g"标志重新启动docker容器,以增加可用的共享内存总量。

docker run -it --shm-size="2g" ubuntu

3.9 RouDi和进程的终止

为了避免Iceoryx posh的未定义行为,建议使用SIGINT或SIGTERM终止RouDi和相应的中间件进程。在RouDi中,我们集成了一个sighandler来捕获信号并使RouDi有机会退出并清理一切。这也适用于进程。因此,建议在进程中添加一个signalhandler(见此示例)。

3.10 如何在Bazel中使用Iceoryx作为外部依赖项

在您的WORKSPACE中定义Iceoryx仓库信息,然后调用load_repositories.bzlsetup_repositories.bzl中的Bazel宏来加载传递依赖项。

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

IOX_COMMIT = "....."

http_archive(
    name = "eclipse_iceoryx",
    sha256 = <sha256 sum of z>,
    strip_prefix = "iceoryx-" + IOX_COMMIT,
    url = "https://github.com/eclipse-iceoryx/iceoryx/archive/" + IOX_COMMIT + ".zip",
)

# 加载Iceoryx的传递依赖项

load("@eclipse_iceoryx//bazel:load_repositories.bzl", "load_repositories")
load("@eclipse_iceoryx//bazel:setup_repositories.bzl", "setup_repositories")
load_repositories()
setup_repositories()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值