[翻译]Iceoryx - 共享内存通信机制

0. 概述

本文简单介绍Iceoryx的共享内存通信机制。

1. 基础知识

当POSIX系统中的一个进程启动时,它会获得自己的虚拟地址空间。

虚拟地址空间的范围可能对不同的进程是相同的,但在特定地址上可访问的数据可能对每个进程都是不同的。

应用程序中的指针使用它运行所在进程的虚拟地址空间。

在进程的虚拟地址空间内,有许多“内存区域”用于加载或映射数据。这些内存区域通常是不连续的范围。一些内存区域的示例包括:

  • 运行程序的执行指令(即程序的.text段)
  • 静态变量声明(即程序的.data段)
  • 运行程序使用的共享库的执行指令(库的.text段)
  • 进程的栈
  • 进程的堆
  • 共享内存段

共享内存段是对进程来说位于某个外部位置的物理内存(例如在RAM的某个部分或文件系统上),通过映射到其虚拟地址空间中的某个内存区域使其可访问。

一个共享内存段可以映射到多个进程,但是在不同进程中的映射地址可能(并且很可能会)不同。

在这里插入图片描述

POSIX API 提供了处理共享内存段的工具

2. 组织结构

Iceoryx系统利用一个“管理”段进行管理目的,并使用任意数量的“用户”段在服务之间进行事件通信。

这些段在逻辑上被划分为“内存池”。内存池包含数量相同大小的“内存块”。

内存块是Iceoryx系统中用于共享内存访问的基本单元。

在这里插入图片描述

Iceoryx系统使用的段数量以及它们包含的内存池配置通过配置文件提供给系统。

配置可以在编译时(作为头文件)或运行时(作为toml格式的文本文件)提供。详见配置指南

3. 零拷贝通信

通过连接的popo::Publisher/popo::Subscriberpopo::Server/popo::Client可以通过共享内存进行通信,实现零拷贝通信。在本节中,popo::Publisherpopo::Server将被称为生产者,而popo::Subscriberpopo::Client称为消费者。

生产者有一个分配的共享内存段,可以将数据写入其中。在POSIX系统中,这纯粹基于文件访问权限决定,因为内存段被表示为虚拟文件。

为了输出数据,生产者在其分配的内存段中预留一个内存块。Iceoryx系统将选择能够容纳输出数据结构的最小块大小。注意,即使数据类型小于块的大小,也会保留整个块。

生产者明确选择何时将写入内存块中的数据传递给所有已连接的消费者(通过发现建立)。当这种情况发生时,指向内存块的指针会放在消费者的接收队列中。消费者可以在方便的时候通过跟随指针访问数据。

消费者必须明确指示何时完成了对收到的特定内存块的处理。当所有已连接的消费者指示他们已完成时,内存块将返回到内存池。

3.1 关于指针的注意事项

如前所述,共享内存段可能会映射到进程虚拟地址空间中的不同内存区域。为了解决这个问题,Iceoryx使用了特殊的指针类型:iox::RelativePointeriox::relocatable_ptr

使用这些类型,在定位内存块时,内存映射的差异不是一个问题。

关于这些类型如何工作的详细讨论可以在这里找到。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个iceoryx发布订阅的C代码示例,其中一个发布者发布一个消息,而两个订阅者订阅这个消息: ```c #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include "iceoryx_posh/popo/subscriber.hpp" #include "iceoryx_posh/popo/publisher.hpp" #include "iceoryx_posh/runtime/posh_runtime.hpp" #include "iceoryx_posh/roudi/introspection_types.hpp" int main() { // 初始化iceoryx runtime iox::runtime::PoshRuntime::initRuntime("publisher"); // 创建发布者和订阅者 iox::popo::Publisher publisher({"Radar", "FrontLeft", "Object"}); iox::popo::Subscriber subscriber1({"Radar", "FrontLeft", "Object"}); iox::popo::Subscriber subscriber2({"Radar", "FrontLeft", "Object"}); // 订阅者1等待消息 subscriber1.subscribe(); printf("Subscriber 1 waiting for messages...\n"); // 订阅者2等待消息 subscriber2.subscribe(); printf("Subscriber 2 waiting for messages...\n"); // 发布者发布消息 printf("Publisher publishing message...\n"); publisher.publish("Hello, world!"); // 等待订阅者接收消息 while (true) { if (subscriber1.hasData()) { printf("Subscriber 1 received message: %s\n", subscriber1.getChunk()->userPayload()); break; } if (subscriber2.hasData()) { printf("Subscriber 2 received message: %s\n", subscriber2.getChunk()->userPayload()); break; } } // 清理资源并退出 iox::runtime::PoshRuntime::shutdownRuntime(); return 0; } ``` 需要注意的是,这个示例代码需要使用iceoryx库,需要将iceoryx库链接到您的项目中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值