儿童网站模板免费下载,网站建设方案前言,创卫网站 建设 方案,网站首页模版目录 原理说明限制条件配置Data-Sharing delivery kindData-sharing domain identifiers最大domain identifiers数量共享内存目录 DataReader和DataWriter的history耦合DataAck阻塞复用 本文详细记录Fast DDS中Data Sharing的实现原理和代码分析。 DataSharing的概念#xff1… 目录 原理说明限制条件配置Data-Sharing delivery kindData-sharing domain identifiers最大domain identifiers数量共享内存目录 DataReader和DataWriter的history耦合DataAck阻塞复用 本文详细记录Fast DDS中Data Sharing的实现原理和代码分析。 DataSharing的概念FastDDS中在同一台机器内通过利用共享内存共享DataWriter和DataReader的history实现通信加速这种方式避免了传输层中的任何开销有效减少了数据在DataWriter和DataReader之间复制所带来的额外负担。
Fast DDS 使用DomainParticipant的 GuidPrefix_t 来识别运行在同一主机上的其他participant。如果两个participant的 GuidPrefix_t 的前四个字节相同则认为它们运行在同一主机上。提供了 is_on_same_host_as() API 来检查这一条件。
使用Data-sharing并不能阻止数据在应用层和DataWriter或DataReader之间的拷贝要避免这种形式需要使用zero-copy通信方式TODO
尽管Data Sharing使用了共享内存但是与共享内存不同的是共享内存是一种完全符合传输规范的方式这意味着使用共享内存传输时被传输的数据必须从DataWriter history 拷贝到传输层再从传输层拷贝到DataReader中。使用Data-Sharing可以避免这类拷贝操作。
原理说明
当DataWriter创建后Fast DDS会预先分配一个位于共享内存映射文件大小为 max_samplesextra_samples大小的样本数的pool当publish数据时DataWriter从这个pool中取出一个sample并将其添加到它的history中并通知DataReader哪个pool中的sample包含了新数据。然后DataReader访问相同的共享内存映射文件就可以拿到由DataWriter发布的数据了。
限制条件
只有当以下条件满足时该特性才可以使用
DataWriter和DataReader可以访问相同的共享内存Topic有一个有界限的 TopicDataType也就是说该数据类型有一个固定的大小限制其成员函数 is_bounded() 返回 trueTopic没有keyedDataWriter 使用PREALLOCATED_MEMORY_MODE或PREALLOCATED_WITH_REALLOC_MEMORY_MODE.
还有一个限制对于DataReader的HistoryQos。使用Data-sharing机制DataWriter的history被共享给DataReaders这意味着DataReaders上有效的HistoryQos的depth最多等于DataWriter的HistoryQos的depth。为避免混淆将DataReaders的 history depth设置为小于等于DataWriter的 history depth。
配置
使用 DataSharingQosPolicy 配置DataWriter和DataReader。配置内容有四种
Data-Sharing delivery kind
有三种模式
AUTO默认值如果DataWriter 和 DataReader符合上述的限制条件data-sharing的传输机制会生效ON类似AUTO但是如果条件不满足entity的创建就会失败OFF不会启用Data-sharing
DataWriter和DataReader的兼容性 《TODO https://fast-dds.docs.eprosima.com/en/latest/fastdds/transport/datasharing.html 6.5.3.1 图片》
Data-sharing domain identifiers
每个entity定义了一组identifiers用于标识它所属的domainTODO一组。只有当两个entity至少有一个共同的domain时它们之间才能够使用Data-sharing。 用户通过DataSharingQosPolicy来定义DataWriter或DataReader的domain。如果没有提供domain的identifiers系统会自动创建一个这种自动的data-sharing domain对于entity运行所在的机器将是唯一的。也就是说所有在同一台机器上运行的entities且用户没有配置特定用户的domains的情况下都能够使用data-sharing传输前提是满足其余的要求。 在服务发现阶段entities之间会交换它们的domain identifiers并检查它们是否能够使用data-sharing来进行通信。 尽管data-sharing domain identifiers是一个64位的整数但是用户自定义的identifiers被限制为16位的整数。这意味着系统内部可能处理更大的64位整数作为domain identifiers然而用户在配置或指定domain identifiers时只能使用较小范围的16位整数。这样的设计可能是为了简化用户接口同时也确保了domain identifiers的一致性和兼容性。
最大domain identifiers数量
在发现过程中从远程实体预期接收到的域标识符的最大数量。如果远程实体定义并发送的域标识符数量超过了这个数值那么发现过程将会失败。
默认情况下标识符的数量是没有限制的。可以通过 max_domains() 函数来改变这个默认值。定义一个有限的数量允许在实体创建时预分配接收标识符列表所需的内存从而避免之后的动态内存分配。需要注意的是数值0意味着没有限制。
共享内存目录
如果指定了用户定义的目录用于共享内存文件那么这个目录将被用来存储用于数据共享传输的共享内存映射文件。如果没有指定则会使用当前系统配置的默认目录。 配置用户定义的目录在某些场景下可能是有用的
选择一个启用了 Huge TLB透明的大页的文件系统来存放记忆映射文件。允许挂载了相同容器的容器之间进行数据共享传输。
DataReader和DataWriter的history耦合
普通的transport传输DataReader和DataWriter保持独立的history每个都有自己的sample的拷贝。一旦sample通过传输被DataReader接收DataWriter就可以自由地从其history中删除sample而不影响DataReader。 使用data-sharing方式DataReader直接访问由DataWriter创建的数据实例这意味着DataReader和DataWriter的history中的samples都指向共享内存的同一对象。因此DataWriter和DataReader的history之间存在着很强的耦合。 这也意味着一种情况如果DataWriter复用一个旧的sample发布新的数据而不是创建一个新的sample那么这个被更新的sample在共享内存中的内容旧变成了新的数据DataReader就无法获取这个sample的原始数据因为已经被覆盖了。 DataWriter如果从其history中移除一个sample只要它没有被复用那么DataReader仍然能够访问到这些旧的数据但如果DataWriter使用同一sample发布了新数据则旧数据会被新数据所替代DataReader也就无法再访问到原先的数据了。
DataAck
使用data-sharing传输sample 的ack在应用程序的DataReader第一次接收到sample时开始通过 DataReader::read_next_sample(), DataReader::take_next_sample()或其他方式。一旦数据被应用程序接收DataWriter就可以自由使用sample发布新的数据DataReader会探测到当一个sample被重复使用时自动从它的history中移除。这也意味着如果尝试连续访问DataReader的相同的sample或许没有sample返回。
阻塞复用
使用KEEP_LAST_HISTORY_QOS 或者 BEST_EFFORT_RELIABILITY_QOS配置DataWriter会从它的history中移除samples并添加新的即使是没有收到DataReader的ack。有一种情况如果发送的频率大于接收处理的频率这会导致在每个smaple被处理前被重复使用。 为了避免这种情况位于预先分配的pool中的samples不会被复用除非它们收到了ack比如它们至少被应用程序处理过一次。如果在pool中没有可复用的sampleDataWriter端的writer操作会被阻塞指导有一个可复用的或max_blocking_time到达。 这种行为不会影响DataWriter的history。samples仍然会按照规则从history中删除唯一受影响的是pool中samples的服用哦个。这意味着即使DataWrtier的history为空但如果pool中的所有samples都没有被确认接收writer操作仍然可能是被阻塞的。 可用通过使用extra_samples 来减少DataWriter在writer操作时被阻塞的可能性这会使pool的分配的大小比history的大小多更多samples从而使DataWriter有更多的机会获取free sample同时DataReader仍然可以访问那些已经被从DataWriter的history中删除的sample。